🔐 Why a popup is not good for security - with video on how to hack your own site to test it

Hey everyone! :wave:

I just wanted to show you guys why a popup is not good enough for security on your site. This is an easy way to hack your bubble site and test your security.

Check it out: https://youtu.be/tLwtXwyYd8U

Editor: https://bubble.io/page?type=page&name=popuphack&id=805testapp42&tab=tabs-1

Preview: https://805testapp42.bubbleapps.io/version-test/popuphack?debug_mode=true

Hope that helps! :blush:

@j805 www.NoCodeMinute.com

For All Your No-Code Education Needs:

  • One-on-One Tutoring
  • eLearning Hub
  • Video Tutorials
  • No-Code Classes

Love this! Airdev also recommends not using popups for this as well! People think that popups with the cannot escape feature does the trick, but that’s just not true.

Check out what Airdev says:


Hi @J805 and @johnny, I agree that popups can be closed using dev tools, but I don’t agree that pop-ups are not secure.

All depends on how you actually manage the data that’s behind the pop-up, if it’s ready to read or it has its own “security” steps that makes impossible to see the data (like using conditions on the background elements).

I.E: https://securitytestblabla.bubbleapps.io/version-test
Editor: https://bubble.io/page?name=index&id=securitytestblabla&tab=tabs-1

However, I agree that isn’t a great idea to “hide” information using popups, when you can just make groups with X conditions that are much safer than that.

I love this kind of stuff, because most likely I already tried to break it :smiley:


Yup. There needs to be more than just a popup. :+1:

It depends on what you are securing though. If you are talking about data in your database, more is needed. Aka, Privacy Settings, etc.

1 Like

Yup. As long as it’s not only a popup, you are alright with covering text as “paid content”. A lot of people think that just a popup would suffice, I just wanted to show that it isn’t enough. More is needed. :blush:

1 Like

It’s a rule: Client side is not the place for security.
So no browser trick can prevent anything.


Correct. :+1: You have to use privacy settings. Thanks for the help clarifying. I think I wasn’t clear enough.

What I was trying to say is, If you are trying to hide something on a page with a popup to cover text (paid content) like a lot of news places do, just a popup won’t do the job.

1 Like

In fact, this is one of the reasons we’re rebuilding some of the plugins on the marketplace. Even the popular [Removed by admin] seems to be exposing data publicly. This could easily lead to a data leak, causing major financial burdens.

One great example is the [Removed by admin] plugin on the marketplace, the secret key is exposed publicly, we had to re-write the entire plugin on the server-side for a private project. For this particular plugin we were dealing with financial data and bank informations, I can’t imagine leaking data on this one.

[Screenshot removed by admin]


Thanks for the heads up about the [Removed by admin] plugin. I haven’t used that one before.

[Removed by admin] too? Really?

Note: See response from [Removed by admin] below to validate the trustworthiness and security of [Removed by admin] and plugins in general too. :+1:

They could change it to private but then the key’s wouldn’t be available dynamically anymore. I think that’s one of the reasons people just decide to expose it publicly, allowing dynamic values.

For [Removed by admin], we made a server-side Plugin with JavaScript, it has dynamic secret key values but entirely run on the server-side.

The list goes on, even the [Removed by admin] Plugin on the marketplace, exposes the data publicly.

[Screenshots removed by admin]


This is what [Removed by admin] says on their documentation.

[Screenshot removed by admin]


@eve, what does Bubble do to check when a plugin is being published to the store? Any suggestions for those plugin developers out there to make sure their plugins are secure? I know Bubble is not responsible for 3rd party plugins, but how do you protect your own plugins that you make?

1 Like

Bubble isn’t responsible for this type of builds, however until they are aware of it and can send out a warning to the developers in question :slight_smile:

1 Like

Hey @J805,

We can appreciate your original post as it highlights the security implications of having ‘hidden’ elements on your page for internal purposes. Numerous Bubblers have employed the strategy of using hidden inputs for calculations, repeating groups for queries and things of the like which are not the most secure nor most efficient. However, what’s more troubling is the misinformation we’re seeing above on plugin security. Seeing a couple of our plugins were mentioned above in addition to a fundamental misunderstanding of API calls, we took the time to shed some light on API basics and Bubble’s options for its plugin developers in an effort to benefit the community.


API Calls

Interacting with a server/vendor for information usually involves an API call; you request some information from a location, you include an API key to identify who you are, you get a response. With the modern web standard, executing API calls is a must not just to request data from other services (Stripe, Google, etc.) but sometimes for your own application. For example, your frontend (also a client) could request information from your backend (as a server) such a user’s profile information or whether they’re even authenticated. The web is a network of servers talking to one another which means one party is requesting information from another who may itself be requesting and returning information, making API calls a facet of web development that every developer should be knowledgeable about.

API Location

API Calls are not exclusive to the client or server, and you decide where the API call must happen as the developer. If you’re accessing your own backend, there’s no way around exposing certain information to the user on the frontend even if that’s a token; take a stroll through your browser’s Network tab to explore the type of information Airbnb, Uber, and Stripe send their own server when you use their frontends. See @vini_brito short’s and sweet comment above as well.

Your user’s browser is making the API call to wherever your backend is accessible, and your backend could very well be executing API calls on its own to get what it needs. Most developers would understand the implications of making API calls to sensitive locations on the client, and thus would very likely build backends that run those API calls instead. Bubble offers the same extensibility with things like backend workflows, as you can easily take API actions from your frontend workflows and asynchronously run them on the backend. The decision lands on the developer as to where to execute an API call, and there’s more than just security and performance to consider.

API Visibility

With the right tools and motive, almost any interface channel can be intercepted. With the few large-scale infiltrations of enterprises highlighted this year alone, everyone is aware security is no laughing matter. One way of preventing a malicious party from comprising any system is lack of visibility, which is a strong argument for making API calls on the server again. Any API call (not just those made from a browser) will not know what other API calls, queries, etc. the destination server will make, as the client you just want what you’ve asked for. The same way you request a retail store employee to find you an item from the stockroom: you don’t have permission to enter and rummage through the racks yourself but the employee does, you don’t know anything about the processes happening, so you just wait until they return and parse the result.

Plugin Security

Bubble allows the plugin developer to decide which keys can be exposed to the client and which keys cannot. As we know, the client is generally considered unsafe in the context of working with and exposing sensitive data while the server is more secure. Separating data across both the frontend and backend may make your development more challenging, but that’s a consideration of numerous factors including and beyond security. Bubble offers plugin developers certain types of fields to aid with the accessibility of information which is worth evaluating.

Field Types

Seeing the fields in your Bubble editor after installing a plugin can certainly make you reflect whether or not they are all required. When developing API actions (not JS actions) for plugins, the structure of the call may require some field values that the developer is knowledgable of but perhaps not their users. There are also cases where keys are required to access an API, on top of the formatting of the call itself to be compliant with what the destination server requires. Bubble solves some of the knowledge-gap and general UX problems of API actions with field types.

Here are Bubble’s own words on field types as shared in the Bubble manual:

  • Public parameters will be modified by the user at the call level (that’s for instance a term for query API call).

  • Hidden parameters are for the plugin builder, and won’t be exposed to the user that uses the plugin. For instance, it can be an encoding type, etc.

  • Secret parameters are good for keys, etc. Users will enter these in the Plugins Tab of the editor.

The field types are determined by the developer based on what they require from their plugin’s users. A common example is the Content-Type header of an API call; most users would not know what that is or what the valid value would be, so the plugin developer may choose to set the value to application/json, application/x-www-form-urlencoded, etc. and mark the whole field as ‘Hidden’ so their plugin users don’t have to see or deal with it at all. If they wanted to expose it to their user in the Plugins tab, they’d opt for Secret. If they wanted to expose it all the way to the workflow action, they’d opt for Public. The decision is made by the developer.

Key Types

When Bubble introduced client-side actions and later server-side actions to match, it gave more reason for plugin developers to take advantage of the Additional Keys section in the plugin editor. A plugin developer could ask for specific keys and values from the user in the Plugins tab and use them at their discretion for operations like initializing elements, executing API calls and more.

There are two types available here:

Public keys are included in Context object and can be accessed for both client and server actions.
Private keys are also included in the Context object are not accessible on the client.

We know these to be true because not only does this inherently make sense as a logical decision from Bubble, but also because it takes almost no time to prove:

  1. Setup additional keys, Public and Private (Privacy - Additional keys - Droplr)
  2. Create client functions, Element and Action (Privacy - Element - Droplr, Privacy - Action - Droplr)
  3. Create server function, Action (Privacy - Server Action - Droplr)
  4. Wire up some workflows for testing (Privacy - Workflows - Droplr)
  5. Throw on a UI and run (Privacy - UI - Droplr)

Results? Both of your client functions will be able to successfully access the Public key but not the Private key, while the server function can access both. Privacy - Execution - Droplr

Key Uses

As seen above, simply setting a value to ‘Public’ or ‘Private’ has nothing to do with exposing data. To reiterate from above, having access does not equate to accessing itself. A good developer would know the implications of their decisions early on, a great developer would know the implications of neglecting proper use. This is a good time to reflect on our own approach for keys, and it’s how everyone should be building plugins: using the service’s own documentation.

Imagine you were building the most powerful payments plugins for Bubble, something that would offer an alternative to Bubble’s built-in integration, really make a difference in what’s possible with Bubble and perhaps even change how people learn by using a third-party service they already know to educate them about development altogether. If you happened to choose Stripe as a plugin developer, landed on integrating PaymentIntents, learned about Strong Customer Authentication and realized you needed to implement Stripe Elements, you would be posed with this challenge from Stripe’s documentation:

Next, create an instance of the Stripe object by providing your publishable API key as the first parameter:
var stripe = Stripe('pk_test_6tv7cR2saQ0So4FmdYhlpkOwgFcl8CuN');

Reference: Stripe Web Elements | Stripe Documentation

A competent plugin developer would understand the following concepts based on their research:

  • Since I’m showing this to my user, it’s on the client not server
  • I need to load a JS library for my users
  • I need to run functions using the JS library
  • I need to show the rendered element from the JS library to my user
  • I need to get the user’s key for my JS library to work
  • I need to ask my user for that key

Therefore, I need access to my user’s key on the client side.

To accomplish this, that competent developer would setup up an Additional Key, set it to Public so they can access it on the client and then pull it to load the library, run their functions and ultimately hit their goal. To add even more confidence into their build, that developer would reference Stripe’s documentation to see if it’s safe or even permissible to pull the Publishable Key to the client which is where they’ll find the following:

Publishable API keys are meant solely to identify your account with Stripe, they aren’t secret. In other words, they can safely be published in places like your Stripe.js JavaScript code, or in an Android or iPhone app.

Secret API keys should be kept confidential and only stored on your own servers. Your account’s secret API key can perform any API request to Stripe without restriction.

Reference: API keys | Stripe Documentation

The above still doesn’t consider the longevity of tokens, functions with external dependencies, and other issues/arguments against running things client-side versus server-side. We’d delve into the basics of the other services mentioned in posts above but that may be better served as a good mental or development exercise for practice with plugin development.

We welcome healthy discussion any time of the day, but sharing incorrect and invalid information that can derail or discourage the community at large is not acceptable. :-1:


Thank you! I am so happy you chimed in here. :blush::+1: Phew! What a relief!

Thank you for taking the time to create such an informative reply!


Lengthy reply that is. Doesn’t change the fact you should never expose private keys on the client-side though :wink:

This is nothing personal to you or anyone else. I’m merely responding on @J805’s topic.


It’s a bad practice, as anyone with minimum browser skills will remove it with inspect tools.

I did a test with conditionals and privacy settings to see “paid” content and it works fine.

1 Like

There are cases when you need to be able to use dynamic keys. A secret key is sensitive data, so you need to take care of this. If you save it on the account or organization level (table), please set up the privacy setting correctly. For instance, Organization A should view Organization A’s secret key. Organization A should not be able to view Organization B’s private key and other sensitive stuff.

Some cases are when a user of Organization A should not view the private key, but you need to execute some API actions using that key. Here, you need, for example, trigger this step on the backend workflow section.

But, we still have an issue here.
This kind of information requires specific skills and experience.
A non-tech person has no clue about these pitfalls and possible implications.
A person/team that chooses the Bubble as a platform for their MVP focuses on starting their project asap. That means they don’t have enough time to get familiar with the platform for getting more in-depth details. So, they miss this crucial part that may get them into trouble or to force additional resources to solve the issue.

I think this responsibility lies with the Bubble team since they do not display any warning information when you install a plugin from the market. Ideally, when a user adds a plugin, highlight somewhere a short description of these pitfalls. On click, redirect to a full article that provides all the information. In that case, we have more chances to warn users.


Hi all,

Jumping in here for a bit of moderation. Thank you to folks who reported this, both here and via email. We’re looking into this situation. As users have pointed out, this is not a security gap on the Bubble platform side, but in how certain plugins are being built. But, there are some things we’re considering on our end to reduce the risk of this hurting users going forward.

For the security of users of those plugins, I have edited posts in this thread to remove specific plugin references. We will be following up with those plugin authors directly. If you know of more plugins that have this issue, please DM them to me or email them to our Success team.

Note that here and in the future with any kind of security issue, we ask that you follow responsible disclosure principles, namely to reach out to us (if it’s a Bubble platform concern) or the plugin creator and cc’ing us (if it’s a plugin) privately, instead of posting on the forum. This gives the plugin creator / us a chance to work on a fix without publicizing the issue, which can then be exploited by others while the fix is in the works.

Given that, I am also closing this thread for now while we deal with this. Again, if you know of other plugins that have this issue, please let us know privately, and we’ll approach that plugin creator.