Is my Bubble app secure?
Bubble writes the JavaScript for you. The data stays safe when privacy rules are tight and when API keys never land in the files a visitor downloads. A public scan can help with the second part. The rules are still your job.
Free check
Check the live app
Paste the public Bubble URL. The check reads what a visitor's browser can already see, then gives you a private report with a fix prompt for each issue.
What Bubble actually ships
Bubble hosts the app and generates the page's JavaScript and JSON. Bubble's docs say those files contain the page's elements, workflows, and other static details, and that a person can read them. Privacy rules decide which data a visitor can find and which fields they can see. The API Connector can keep a key on the server when the parameter is marked private. The Data API follows privacy rules for a normal user, and Bubble's docs say an API token ignores those rules and acts as an admin. There is no single React or Supabase stack underneath a typical Bubble app.
Mistakes worth checking
These are the ones that show up in apps built with Bubble. Each step is something you can do in the browser or in the product dashboard.
High
Privacy rules that let everyone find private things
Each data type has privacy rules. The role "Everyone else" with "Find this in searches" and "View all fields" on a User type, an order, or a message is how a customer list becomes public. The free check does not evaluate these rules.
Check it yourself
In Data, then Privacy, open every type that holds personal data. For Everyone else, turn off finding it in searches unless the type is public on purpose, and expose only the fields a stranger should see. Repeat for any logged-in role that should not see other people's rows.
Critical
An API key stored on the page
Bubble's docs say not to put API keys in option sets, on-page workflows, elements, dynamic expressions, app texts, custom states, or URL parameters. Those can show up in the downloaded files. In the API Connector, mark sensitive parameters as private so Bubble sends them from the server.
Check it yourself
Load the live app, open developer tools, and search the downloaded files for the key. In the editor, search option sets and on-page workflows for the same value. Move it to a private API Connector parameter.
High
A Data API admin token in the client
Enabling the Data API exposes the types you check, still filtered by privacy rules when the caller is a user. Bubble's docs say an API token skips privacy rules and has admin access. That token is a password. It does not belong in a page, a plugin, or a public workflow.
Check it yourself
Under Settings, then API, enable only the types you mean to share. Search the live files for the token. Prefer a signed-in user when another app needs the data. If the token has already been in a page, generate a new one.
Medium
An HTML element that embeds another backend
Some Bubble pages include an HTML element that loads Supabase, Firebase, or a script with a hard-coded key. That snippet is part of the page a visitor downloads. Supabase still needs row-level security. Firebase still needs rules that are not test mode.
Check it yourself
Search HTML elements for supabase, firebase, sk-, and sk_live. If a supabase.co address and anon key are there, confirm row-level security in Supabase. If a Firebase config is there, confirm the rules require a signed-in user.
Low
Browser headers, after the data leaks are closed
Missing headers such as Content-Security-Policy are worth adding, and they are much less urgent than an open privacy rule or a key in the page. Bubble's hosting sends the headers it sends. You may not control all of them.
Check it yourself
Run the free check and read the header note if one appears. Fix a leaked key or an open privacy rule first. Add headers when the host lets you, without blocking the app's own scripts by accident.
A prompt you can paste
Paste this into Bubble, publish again, and run the check a second time. If a key was already on the live site, rotate it in the vendor dashboard. The prompt cannot do that part.
Review this Bubble app's security settings and page content. Do not weaken a privacy rule to make a repeating group show data. 1. For every data type that holds private information, set privacy rules. For the role Everyone else, turn off "Find this in searches" unless the type is public on purpose, and expose only fields that strangers should see. Do the same for signed-in users so they cannot read other people's rows. 2. Remove API keys from elements, workflows, option sets, custom states, app texts, and URL parameters. Store them as private parameters on the API Connector so the call runs on the server. 3. If the Data API is enabled, expose only the types that need it. Remove any admin API token from pages and plugins. If one was exposed, regenerate it. Prefer user authentication over the admin token. 4. Search HTML elements for third-party keys and for Supabase or Firebase clients. Keep Supabase row-level security on, and do not leave Firebase in test mode. 5. Tell me which keys were visible in the app so I can rotate them. Do not print the secret values.
What the check looks at
- The public page and the JavaScript it loads, for common leaked secret keys: a Supabase service role key, OpenAI, Anthropic, Stripe secret keys, AWS, GitHub, Slack, private keys, and database URLs that include a password. A Supabase anon key is called out as expected in the browser.
- A short list of public paths: /.env, /.env.local, /.env.production, /.git/config, /.git/HEAD, and /.npmrc.
- A source map, only when a script on the page already points at one, and only when that map includes original source.
- Supabase tables, only when the page already includes a supabase.co address and the public anon key. It asks for one row per table, then drops that row.
- Firebase Realtime Database and Firestore, only when the public config is already in the page. It uses that public config and does not sign in.
- A few browser safety headers on the main response. Missing headers are noted when two or more of the watched ones are absent. They are less urgent than a leaked key.
What stays outside it
- It reads. It does not log in, submit forms, or change data.
- It does not guess passwords, fuzz inputs, or hunt through hidden paths.
- It does not use any secret it finds, including a service role key.
- It does not open your builder's dashboard. A rule that lives only there can stay invisible.
- A clear result describes this public look. It is not a certificate that the whole app is safe.
- Bubble privacy rules and the Data API are not tested. A key inside the downloaded page can still be found. Public .env and .git files are uncommon on Bubble's own hosting, and the check still requests those paths.
Questions
Free check
Run it on the published URL
Use the address a customer would type. The report stays private, and the shareable scorecard hides the details.
Other builders
- Is my Lovable app secure?Service role keys, row-level security, and variables that ship to the browser.
- Is my Bolt app secure?Vite variables, Supabase locks, and Bolt Database access you confirm by hand.
- Is my Replit app secure?Secrets in the page, a public Repl, and DATABASE_URL where a visitor can read it.
- Is my Cursor app secure?Client env prefixes, row-level security, Firebase test mode, and source maps.
- Is my v0 app secure?Next.js client bundles, Vercel env vars, and optional Supabase or Neon.
- Is my Base44 app secure?Entity rules you check by hand, plus Vite secrets and service-role calls.
- Is my Windsurf app secure?Agent edits that ship a secret, loosen a database rule, or publish a source map.