Legacy
Essential security practices for every Bubble.io app developer
Photo by Kaffeebart on Unsplash
Introduction
Everybody wants their web app to be secure, with cyber attacks remaining a persistent and growing threat to IT professionals and business leaders.
Web application security is a spectrum from less secure to more secure. This article is a starting point for Bubble Developers to understand the main areas of risk and raise awareness of how to improve security in these areas.
We cannot cover everything here, as many security implementations relate to specific application use cases. We do have a professional-level Bubble Bootcamp in which we cover how to implement these principles in detail.
Rule of least privilege
Firstly, it is a good idea to follow the rule of least privilege — i.e. restricting access to data or the ability to trigger workflows to the bare minimum for each entity within your app, be it a user type or a connection between your app and another app via API.
This minimizes the surface area in which your apps are exposed to risk. Don’t leave open doors for bad actors.
Set application rights to Private
In Settings on the General tab, always set your “Application rights” to Private. Otherwise, everyone can see your full database AND any API keys you might have stored in plugins or workflows.
Implement secure account practices
Enforce confirm email workflows, set a password strength policy, and preferably insist on 2-factor authentication and automatically logging out users after a certain duration of time.
This is a balance between user inconvenience and security, but everything your users can tolerate will help make your app more secure.
Restrictive page conditional on a parent “Security Container”
Create a parent Group element on your page and call it “Security Container”. Set “this element is visible on page load” = False and create a Conditional on this element that sets this value to true only when specific criteria are met, e.g. “Current user is logged in and Current user Role is Admin”.
Clean up test pages
Avoid creating test pages, for example, pages where you might have a button that triggers backend API Workflows for testing. Either put your test pages in a group with a restrictive page conditional or create them in a reusable element so they can’t be accessed without being placed somewhere.
Configure appropriate privacy rules
Privacy Rules control which users can see which tables, columns, and rows of data within your app — at the database level.
Understand privacy rules and configure them according to your use case, or your data will not be secure. For example, “Current User is logged in” is a very permissive privacy rule. It allows anyone with an account to view all the data in that data type. Image if this was a privacy rule on the User data type or on other sensitive data types. Not good!
Always disable the default “Everybody else (default permissions)” privacy rule, and instead create rules that grant specific access, unless you are 100% fine with the data in this data type being publicly accessible on the internet.
Keep option sets for non-sensitive data
Option sets are designed to store short, static lists of data that are fast to load. But they are public.
Never put API keys or sensitive data in Option Sets. Use a database table instead, and secure it with privacy rules.
Don’t pass sensitive data in URL parameters
Yep just like Option Sets, URL parameters are also public. Don’t put sensitive data or keys there either!
Upload sensitive files and images as Private
Set Image and File Uploaders to upload files as Private Files = True, otherwise, they are publically accessible to anyone with the URL.
Keep Backend API Workflows set to Private
Don’t enable “Expose as a Public API Workflow” unless you need other apps on the big wide internet to access this API Endpoint. Every API Workflow that is only used within your app should be private to your app only.
If you do require a public API workflow, don’t enable “This workflow can be run without authentication”. At a minimum, require the user to specify your app’s token in the query string, or better still, actually authenticate the connections to your app’s API workflows.
Don’t enable the Data API
Don’t enable your data API if you don’t require it to be enabled. If you do require it, only enable the Data API on the data types that you require.
Store API keys in “private” parameters
If possible for your use case, use the Private functionality to prevent the API key from being set within your app.
Update access tokens in backend workflows
Some data is so sensitive that it shouldn’t ever be accessible to a frontend user even if stored in a database table, such as a Client Secret or dynamic Refresh Token for a web service.
Where possible, store this data in a data type with very restrictive privacy rules, and interact with such data from Backend Workflows that “ignore privacy rules when running this workflow” = true.
This way, sensitive keys are never sent to a frontend user’s browser, even if they are a “trusted” logged in user.
Document areas of risk
Know the risks and document where they lie within your app. For example, the User data type is very important when configuring Privacy Rules.
Document when critical fields on the User should be set (e.g. Setting a User’s Company when the user is created) and when they shouldn’t (at any other time) to prevent future developers or yourself from making mistakes.
The same is true for API Workflow settings, e.g. if it is public, document why.
Write logic to be explicit vs implicit
Write logic in a way that will force your app to be secure, even if there is a future change by another dev, or a mistake or edge case later on in a workflow.
For example “Current User Role is Admin” is explicit, while “Current User Role isn’t Agent” is implicit and more permissive, and may cause issues down the track if other User Roles are added.
Use restricted keys on external services (vs keys with full access)
If external services provide an API key, or your app provides an API key for other apps to access, use keys with restricted functionality rather than full admin rights. A great API to see this on is Stripe, with many configurations of an API key possible.
Next Steps
We hope you have found this helpful.
If you’d like to learn how to configure your apps to be secure, including an in-depth demonstration of how to implement the principles described here, please consider our Momentum Academy Bubble Bootcamp.
We also undertake audits and can work with you to help make your app more secure. Please contact us via the contact page if you have any questions.
Where this story went
We spent five years mastering Bubble. Now we build with AI.
Momentum was one of the world's leading Bubble.io agencies — that's why we wrote this article. These days we build and migrate the same kinds of products with Claude Code: real, portable code your own team can amend with AI. If you're weighing up a move off Bubble (or any platform), we've made the journey ourselves.
Related posts
Legacy
**What a Founder’s 1,500-Prompt Failure Taught Me About AI and Vibe Coding**
Recently I had a call with a founder who was looking for advice about building with Bubble.io. He came to me after experimenting with vibecoding , an emerging…
Legacy
In the brave new world of AI coding: Why we’re doubling down on Bubble.io in our agency/venture studio.
Introduction Tool obsession It’s 2025. There’s lots of excitement/hype about generative AI and coding. There’s also a small ocean of opinions about the various…
Legacy
Why Learning Bubble Still Matters in the Age of AI
If you’ve been curious about building apps with Bubble.io, you’ve probably asked yourself at least once: “Isn’t AI going to do all of this for me soon?” It’s a…