Huge Security Issue with API Calls

Hi.
Either I just found a big flaw or I’m missing something obvious. You decide.

I set up my api calls in the Bubble’s API connector with private keys in header and they’re working. There’s no problem with the keys. If you look at the network tab in the website, you’ll see that Bubble makes POST calls to “https://csgoracle.com/apiservice/doapicallfromserver” with no Authentication ?! It is set to NULL.

And here comes the worst part:
Anyone (I really mean it, even you) can make a post call to “https://csgoracle.com/apiservice/doapicallfromserver” with the payload shown on the image and get the private data which should have been only accessible through my website. I already tried! See:

More info:
Those api calls are made to my endpoint on PythonAnywhere. They are responsible for getting data from there.

Hey @kyazogluu :wave:

If you checked the option to expose your endpoint, anyone can find and use it. That is the point of expose your webhook, so other Apps/Systems can be integrated to your Bubble App. There is nothing wrong here…

What you can do is make your data private, so it will be accessible and viewed only for the correct users.

Other thing you can do is to create your own API KEY / Secret. And configure your backend workflow to run “Only When” the provided key matches the correct Key.

Hi @rpetribu
First of all it’s not a Backend workflow. It’s an API call that I set up in the API Connector Plugin.
Where is this “expose your endpoint” option? I certainly don’t want to expose my webhook.

About making the data private, which data? I don’t see anything related when I go to Data > Data types or Data > Privacy tab. Because the data I’m trying to hide is not in the database, it’s coming via an api call.

Am I clear enough? :slight_smile:
Expected → User gets the data via api call when they’re on my website
NOT Expected → User can’t get the data outside of my website

So, if I understood correctly:

  1. You are making a get call from your bubble app to a service where some data is hosted.
  2. You have set access keys to that service in the header of the calls as private
  3. Bubble seems to be hiding the keys correctly, as they are not exposed in the payload
  4. However, anyone that copies the payload from the browser console and uses it in another call gets access authorization to the host service.

Is that it?
If that is correct, it is absolutely terrifying.

Are you sure the problem is not with the host service that is giving access without authorization?

1 Like

Almost certainly this.

3 Likes

Hi. @di_lucena @NigelG
Yes, that is what I meant.
Well, the problem may be caused due to the endpoint on the PythonAnywhere. Because I set it up also, I may have done some mistakes. But, even if that is the case, why do I see “Authentication:null” in the network tab? Bubble seems to be making an api call with no auth at all.
I’m gonna try to debug my endpoint in PA.

Update:
I forgot to inform the Forum but I talked to Eram from the Support Team. He carried this case to technical team and informed me frequently. He did an excellent job.

The result is
Bubble has indeed a huge flaw with API calls with “Data” type. The following statement was from him, at the end of our discussion:

Though somewhat unrelated according to our engineers, one thing worth noting is that the API Connector’s Data API calls wraps into a different format and then ships server-side without exposing the private keys. However, this is still a public call and so can generally be made by anyone. This is a known limitation for now, which we apologize for, but I can submit this as formal feedback to our respective teams for them to more seriously consider improving in the future, though we’re of course always thinking about how to improve security.

So, no, it was not about the host service or their authorization system. @NigelG @di_lucena
Best regards.

2 Likes

I don’t remember where I read this, but I believe the only reason you’re seeing “NULL” in the authentication is because Bubble is hiding the private key.
Also, if you’re concerned about revealing the call URL, you can replace the URL with a parameter that you can make private. (This is suggested by @petter in “The Ultimate Guide to Bubble Security”)

1 Like

I’m confused. If the host server is setup to require authorization, then how can Bubble’s ‘wrapped API call’, without the correct authorization header make a successful call? Surely the server would return a 401?

Clearly missing something here.

EDIT
Oh wait - the authorization header is sent from Bubble’s server. The public call from client is made to the Bubble server to trigger this. I guess the server can retrieve the authorization values server side when it makes the wrapped call.

Is that right?

1 Like

Maybe a way to save on WU :stuck_out_tongue:

1 Like

Hi,

Thanks a lot for all the info you gave.

It’s 2025 and the issue seems to be still here - leading to some vulnerabilities, eg to SSRF attacks.

Were you finally able to circumvent the issue ? If so how ?

I would be grateful for any additional info !