Why all of your server-side redirects are insecure

Thanks for confirming. That seems to have been the case from the various tests. The question is what caused the individual data request charge of 0.02 WUs when button clicked whose triggers evaluation is false but has a workflow action of create a thing, which doesn’t run since trigger evaluation is false…and why that individual data request charge of 0.02 WUs is not charged if the create a thing action is not present or replaced by a show alert action, and again keeping in mind, the trigger condition evaluates to false so no action is ever actually initiated.

Maybe it is just one more undocumented thing in the intertwined and obscure universe of WUs. Maybe just invoking these actions related to server side process, even if nothing is actually accomplished, costs WUs.

2 Likes

I think this post (and the accompanying section in the manual) misses the point by overemphasizing the CDN links. The HTTP redirects are inherently insecure because you can just ignore them. It is trivial to do so. No one is going to bother with guessing a 25 character randomly generated string. If they could do that, Bubble would have bigger problems for tangential reasons I don’t want to get fully into.

The problem is that the redirect is not being handled internally in a way that’s completely hidden to the client. This probably has to do with some sort of technical debt or performance reason. The Bubble engineers in this case have stated a half-truth. I am not sure what happened to Payam Azadi (his account is no longer active) but the next Director of Platform/Reliability/whatever has to focus more on tightening up security.

Most Bubble apps are bootstrapped so protecting intellectual property is even more important for these users.

They haven’t.

If they were to change this behaviour, they’d have to verify that the user has permission to download the page’s code for (at least) every page that has a server-side redirect before the user can retrieve it from the CDN. That will add to page load times.

You don’t have to randomly guess.

Bubble doesn’t need to change this behaviour, but the fact remains that as of now, it is hard to build secure apps by default. The current approach is:

  1. Client side workflows are pretty easily manipulatable
  2. Move everything to backend
  3. Set up API calls that return data from backend where necessary via API Connector

And then, at that point, you realise if you’re setting up API calls for every little thing you want to do in your app, you might as well just use Xano. And then you realise, why would I use Bubble as a front-end when WeWeb exists?

Things that Bubble can do to improve platform security include:

  1. Stop exposing API workflows as public by default
  2. Provide a simple method to verify an API workflow is being called from within the Bubble app (e.g ‘allow authentication with admin token only’)
  3. Allow returning data from backend workflows natively (trigger API workflow rather than schedule API workflow)
  4. Sanitise API connector response schemas (this is dead easy and still allows preserving the type info, so I don’t know why it’s not done)
  5. Allow dynamic expressions to be saved and reused (‘dynamic variable’). e.g I should be able to create ‘Current User’s Role is Admin and Current User’s email contains @notquiteunicorns.xyz’, save it as a variable (using the same UI as return data from custom event), and use it in a dynamic expression. In practice, a dynamic expression would be much like a custom event, in that it can take data as parameters, but it can be called from a dynamic expression and return only one value / type.

1/2/3/4 should exist by now. 5 is more complex but really makes Bubble a more powerful tool.

5 Likes

Privacy rules don’t add latency to data requests, you can test this yourself in the network tab.

Been doing this from day 1. What’s funny/bizarre is a Bubble engineer recently stated this was a bad practice from a security standpoint.

Yes. More generally, we need API token scopes, it’s actually disgusting that there’s a single global API token that gives admin access. Same for “Ignore Privacy Rules.” We should be able to narrow down which privacy rules are being temporarily ignored. There’s a huge lack of granularity.

Still the most glaring deficiency of the platform that needed to be fixed years ago.

Yeah, funny you mention that. Probably .01% of people go through the trouble of manually doing this. But even if you do sanitize it the field structure and names remains visible. I don’t think there’s any reason for it to show up at all in client side code if you set up API calls to be serverside only.

Yes, I’ve repeated this 10x in the last few months. This is more important than any of the UI stuff they’re doing. The lack of this feature makes me think I’m wasting my time on Bubble instead of using an AI tool. You literally can’t CTRL + F expressions, you have to manually change them like the 1980s. @MattN had a kind of neat workaround for this that he posted recently which is to use the properties of a reusable event, but this is super hacky and still not exactly what we need.

Here’s a snippet from the manual page I shared:

To make sure a condition is processed server-side, you can involve anything having to do with the database or user authentication. For example, Current user is logged in and Do a search for:count > 0 are both conditions that Bubble will query the server to process.

Based of the above, your “Current User is Logged in” expression is making that individual data request since it’s a server side expression.

Whereas “Current User Role is Admin” is already loaded in Current User so no request.

I don’t think that is what is happening because it doesn’t explain the actual issue, which is why would that not happen when it needs to evaluate the condition to determine if the alert should be shown or not? It is the same condition, that is on the same trigger, the only difference is one test used an action of create a thing (this incurred that individual data request of 0.02 WUs) and the other used an action of show an alert (this did not result in an individual data request of 0.02WUs).

Also, is the implication of your suggestion that the current user evaluation is done server side, so requires an individual data request? And since the condition is ‘current user is logged in and current user role is admin’ wouldn’t the entire condition be evaluated server side?

A wholly client side workflow that shares an alert will not touch the server when the condition can be evaluated by the client (even if it is exploitable). A workflow with an alert and Current User’s Role is Admin will be exploitable, but not run an individual data request. Add a Create thing action and the alert will likely run, but the Create thing will likely not run. It may charge for a data request though I would not expect it to.

In any case, WU is not the main impact of this issue so would be worth creating another thread if you want to probe it :slight_smile:

Based on the wording in the documentation what you say can be true but since there is only one individual data request we can assume 2 things:

  • that even when the condition is processed server side only necessary data requests are charged. Maybe the client side value is passed to the server?
  • we know that expressions are evaluated from left to right, we can assume Bubble decides when to call the server at individual points of the expression. Could be that there’s an individual data request charge per each segment of an expression that calls the server?

Maybe caching of data requests played a part?

While WU isn’t the point of the topic, I believe that knowing at what point an expression has to be verified server side can help build good security practices.

2 Likes

Thanks for that…pretty different approaches to what I was doing in an attempt to understand more of the need to use conditionals to secure the workflows and to use conditions that are evaluated server side and not client side.

Is a condition to be added to the workflow event triggers or the workflow action steps? In my test I added it to the workflow event trigger using a condition ‘current user is logged in’ to force a server side evaluation. Would you say based on the experience you have of hacking bubble app event triggers and action steps that having the condition on the event trigger is less secure than having the condition on every action step?

Without a privacy rule in place, which yes, privacy rules are the only way to protect your data, wouldn’t the current user’s role is admin as a condition on a event trigger or action step be open for a bad actor to change since in the manual it doesn’t imply that a condition of ‘current user role is Admin’ would force a server side evaluation and that evaluation would happen client side, making it possible to change? As it is understood that the current user is downloaded onto the client device.

And if a privacy rule of current users role is admin is applied, wouldn’t that suffice and the use of the same condition of ‘current users roles is admin’ on an event trigger or action step just become redundant? If the privacy rule precludes the data from being found in a search, than it wouldn’t be possible for the bad actor to find it to use in an action?

In an attempt to make the most out of the tip, I’m trying to figure a way to use a condition that evaluates server side, not client side, and understand the WU impacts as well as redundancy related to existing privacy rules. I wouldn’t want to add conditions everywhere that are exploitable, are redundant against privacy rules and create extra WU charges.

Do you know if a condition like ‘do a search for users: constraint email is current user email and constraint role is admin: count>0’ will sufficiently replace a condition of ‘current user is logged in and current user role is admin’ so as to force the server side evaluation of the condition while essentially being the same thing, since a user can not be logged in without an email and user role is gets added to the search constraint rather than appended to the condition after AND operator?

This I believe maybe the case that the expected ‘create a thing’ from the client side action is sent server side as a unique ID to do an individual data request to evaluate if it can be run or not, but I’m waiting on support to clarify this. I tested by adding multiple create a thing actions and expected multiple individual data requests, but that didn’t happen, so still a bit confused on exactly why this charge occurs.

2 Likes

Event trigger

What I’ve found happens in this case (when a user has falsely given themselves the conditions to run the workflow):

Client side actions in the workflow run, including alerts etc. Server side actions like creating / updating things do not run and return an error behind the scenes.

Of course, your mileage may vary and I haven’t gone too deep yet.

Okay, so this would imply that using a condition that is evaluated client side is sufficient to protect against server side actions present in a page workflow series from running.

And I know you want to avoid discussing WUs, but when running this with a conditional evaluated client side, there is still a charge of 0.02 WUs for and individual data request…this seems like a bug as we should not be charged anything.

Seems fishy that if the conditional evaluation of the trigger returns false that there is a need for bubble to do anything within the series of workflow action steps. I’ll patiently wait for Bubble explanation.

Adding “admin only” conditions on workflows on Admin pages isn’t demanding - it is an easy best practice for Bubblers to adopt.

3 Likes

My current setup for permission level pages includes not even loading data if a User’s permissions don’t match. So if they bypass the redirect and remove the “Warning” floating group, all they get is a blank UI.

Invisible UI is still accessible

As in the UI will be there, but no data will be loaded and all admin WFs have a permissions check.

I don’t store Searches in any element data sources. All retrieved data is stored in states.

2 Likes

This needs to become as 2nd nature to Bubblers as “privacy rules are the only way to protect your data”

1 Like

Doesn’t matter, they can run searches without needing that page. Your privacy rule either allows it or it doesn’t.

Anyone can directly query the Bubble DB, it doesn’t even matter if the entire page is password protected.

The only bit of security Bubble offers is security rules, most of the rest is leaked to anyone who asks

Of course privacy rules are in place. I structure my database around using privacy rules first. Control of data loading on a page is my way of putting in place additional security controls, WU optimisation and UX.

For example in my ERP. All data types have explicit privacy rules, depending on the below or, more commonly, a combination of:

  • if a user is an enterprise user
  • if a user belongs to an organization that owns the data
  • if a user belongs to the department that owns the data
  • if a user is an admin

No one rule will have ever have access to all fields. I handpick every single one depending on use cases. I create satellite data types for public/shared data.

1 Like