Why File Upload API Endpoint is Restricted the Way it is?

I’m having a hard time understanding the chosen implementation for a ‘fix’ for the file upload api endpoint. As can be understood from the Bubble Manual that it is WAY TOO RESTRICTIVE

Don’t allow file uploads to the file upload API endpoint

This setting disables the fileupload API endpoint, which can improve security by preventing direct access to that upload route. However, it does not disable all file uploads—it only blocks access via the fileupload endpoint, which certain plugins and workflows rely on.

How this affects file uploads:

  • If the checkbox is checked (i.e., the fileupload endpoint is disabled) file and image uploads will work as usual:

    • File and image uploads through the Bubble editor still work—this includes actions like setting images in the property editor or uploading directly to the File manager (if the collaborator has permission to edit the app’s data)

    • File and image uploads in runmode using Bubble elements like the File uploader and Picture uploader also continue to work (unless they are prohibited by conditions or privacy rules), with the following exceptions:

      • Picture uploader: if limit image size before upload is enabled, it will not work.

      • Non-standard upload location: if you are using a non-s3 storage (e.g. Box), it will not work.

    • The fileupload endpoint remains disabled for all other access, including for plugins or custom calls—this may cause certain Bubble-built or third-party plugins to stop functioning if they depend on it.

  • If the checkbox is unchecked (i.e., the fileupload endpoint is enabled):

    • There are no restrictions on file uploads—any part of the app or plugin can use the endpoint as usual.

Is there any technical reason at all it could not have been implemented in a more thoughtful approach? I see this as either you restrict via the checkbox and are then forced into

  1. Only using Bubble File and Picture Uploader Elements
  2. Not being able to restrict the limit of the image size before upload
  3. Using only Standard S3 upload location
  4. deal with the minefield of which Bubble-built or third-party plugins will stop functioning

It seems like it is NOT a REAL FIX, and more or less only fixes a security flaw for those apps that choose to deal with the 4 issues stated above.

WHY would it not have been possible to just simply adjust the way the fileupload endpoint works so as to require an AUTHORIZATION HEADER in the form of an ADMIN TOKEN if the checkbox for restricting file upload API endpoint is checked? Wouldn’t it make a lot more sense to say that the dozens of plugins available that use this endpoint will continue to function so long as the plugin developer updates the plugin so as to use an Admin Token in an Authorization header, which will actually deliver a REAL FIX so that users can restrict the unauthorized usage of the API endpoint?

I just do not understand how this is considered a fix to a security flaw in its current state.

Are all 99 of the plugins found using search term ‘upload’ now obsolete if the app owner chooses to restrict the access? My thought is yes, they are. So wouldn’t it have been wiser to say all 99 of those plugins can still be used, and the security flaw can be fixed, if the plugins are updated to included an Authorization Header?

I’m not really good at prompting ChatGPT to explain to me security issues, so maybe somebody with more experience in that could help. @georgecollier any insights on why the Authorization Header wouldn’t not work?

  • there are valid use cases where unauthenticated users need to be able to upload files from the client
  • if you require an admin token, that admin token has to be retrieved from somewhere (you obviously can’t send it from the client)
  • file has to go client → Bubble server → S3
  • this actually wouldn’t be any more secure than the previous status quo as we just send the file to the Bubble server where it’ll get uploaded

Okay, so that is solved by not checking the box to restrict access to the file upload api endpoint, because if I do check the box to restrict access to the file upload api endpoint, an unauthenticated user would not be able to upload files from the client, unless the app is using the bubble file uploader or picture uploader (without limits to the file size). That means, you either keep your api endpoint open and not secure to allow the valid use cases of unauthenticated users to be able to upload via the client, or you close it and secure it which removes the ability for that valid use case of unauthenticated users to be able to upload via the client.

A thoughtful approach is to allow both things to be possible. This is akin to thinking logical building a bubble app and modularity…if we give an optional Authorization Header, then we get best of both worlds, an valid use case for unauthenticated users (optional authorization header is empty) and we can close the api endpoint and keep it secure. Plus as a developer, if I know the limitation, I can work around it, like make the api call run on the server where I can search for the admin token or have it static and pre-defined in the backend workflows (which I would secure).

Sure, that can be done on a backend workflow where the file can be uploaded. The overall point here is that Bubble didn’t take a full thoughtful approach to this, especially in consideration of the impact on plugins. So, if a Plugin were to need to retrieve the admin token, that would be done via a Secret key, either on the API call in the Plugin API Connector, just like it is for any other plugins that require API Keys, like Stripe. Are those keys a security issue? My understanding is that they are not and are secure, but in your work with NQsecure do those API keys show up as a security concern?

And for anybody not using a plugin but is using the API connector in the app directly for use of file upload api endpoint, they can also set their Headers as Private for security purposes.

As what @Jici says here about the API Key, that would be true for an Admin Token used in the Headers as Authorization as well. So it seems like there is no valid technical or security reason for not following a more versatile approach and security minded approach by altering the API endpoint to have an optional Authorization Header that is set to Secret. Unless I am misunderstanding how security works for API calls and API Keys.

Not really. I have a plugin that has server side actions for uploading via the file upload api endpoint. It takes the Blog from AI for images, which can not be uploaded via front end due to CORS so I upload via backend…these blobs never interact with the client device at all, since client device is not used by the server. Additionally, I would imagine most uploader plugins are needing to do the same things, which is to take the file, turn it into a blob, and then use that blob URL to send via file upload api endpoint. I have an uploader element that just needs a URL to an accessible image or file, so no file is ever interacting with the client device at all, it is just text.

Additionally, the security flaw in Bubble was not related to files hitting the client device, it is the ACCESSIBILITY of the file upload api endpoint, which now, if we want to fix that security flaw, we are only able to do so if we chose to only use Bubble file uploader and bubble picture uploader (with no limit on file size set)…so for me, this doesn’t fix the security flaw, it just makes everybody aware of it.

The security flaw is not the file, it is the accessibility to the file upload api endpoint. At least that is where my mind is, unless Bubble thought the security issue was that any file can be uploaded as the security flaw, which if that was the case, why didn’t they add some kind of tool to their uploaders to verify the security of the file before uploading it to the file manager?

It seems to me, and I might be wrong, as I do not have a fully fledged understanding of all the nuances around security and protecting certain things, is that this ‘fix’ is not a fix at all and was implemented with a conceptual misunderstanding. To me, the security issue is that I can not close my file upload api endpoint with a Key (ie: an admin token), and any bad actor can just upload files of any type (even cute little non threatening bunny rabbit cartoons) to my file manager.

There are already known ways to make things like admin tokens or api keys secure in Bubble api connector and in plugins, so why didn’t they use that route? The issue is they seemed to take a lazier approach, which is ‘just turn it off’, so with the key analogy, instead of adding a new deadbolt onto the door, they just removed the door knob and sealed up the door frame.

Bubble has made it now, that if you want to secure the file upload api endpoint, you have to turn it off, and use only the two uploader elements that work with Bubble, OR, keep the file api endpoint not secure and open so as to continue to use any plugins or backend workflows etc. that an app has already been using.

Usually I would say the goal should be to fix the problem, without causing others. In this Bubble did not do that, since it is a breaking change if somebody wants to continue to use the file and picture uploader functions they have built, but want to take advantage of securing their app a bit more and close off unauthorized access to the file upload api endpoint.

Or is my understanding of security related to API keys wrong and that in Bubble there are no secure API keys?

@boston85719 I think they likely wanted to cover this security issue as a first instance and the use cases you describe would be quite complex (e.g. expiring upload tokens) to implement and aren’t as high as the other priorities at the moment. I wouldn’t say they caused other problems, it’s just a tradeoff.

I do think a short term improvement (and maybe low effort) would be at least allowing the API calls via an Admin token so that at least these could be sent to a closed endpoint to the backend via Base64.

1 Like

We are on same page then. I didn’t say anything about expiring upload tokens, I was talking only about authorization header using API Token.

But did say it should be optional, which would say, if endpoint is closed the lack of auth header makes so call fails. The need for optional is on bubble side to set system to check if endpoint is closed and then check optional auth header.

So I believe we agree, low effort, big improvement, use auth header with api tokens.

I really dislike Bubble’s use of “all or nothing” API tokens, they need to be scoped out to be more modular. This is just one particular instance of a larger problem.