Is my Base44 app secure?
Base44 gives you the database, the login, and the React app in one place. The locks on that data are Base44's own rules. A public scan cannot open them, so this page splits the work: what you confirm in Base44, and what a stranger can already see in the published files.
Free check
Check the live app
Paste the public Base44 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 Base44 actually ships
Base44's developer docs describe the frontend as React, React Router, Vite, Tailwind, and shadcn/ui. The backend is Base44's: a managed NoSQL database, built-in auth, and serverless functions on Deno. Site hosting serves a static build. Entity access uses row-level and field-level security. Their docs say base44.asServiceRole skips those rules and is for backend functions. Deploy Safely does not call the Base44 API.
Mistakes worth checking
These are the ones that show up in apps built with Base44. Each step is something you can do in the browser or in the product dashboard.
High
An entity with no row-level rule, or with read set to true
Base44's developer documentation says an entity with no row-level security rule is accessible to every user. A read permission of true allows every caller, including someone who is not signed in. Field-level rules matter too: a record can be readable while one field on it should stay hidden.
Check it yourself
Open each entity's security settings. Private data should require a signed-in user, usually by matching the record's created_by to the current user, or by checking a role. Do this even if a public scan looks clean. The scan does not query Base44.
Critical
asServiceRole inside the React app
Service-role access skips row-level and field-level security. Base44 documents it for backend functions, where you are responsible for any check the rules would have done. If that call is in a component, the visitor gets the same bypass, or the bundle reveals how the admin path works.
Check it yourself
Search the project for asServiceRole. It should appear only in backend functions. Then search the published JavaScript. If the string is in the bundle, move the call to a function and redeploy.
Critical
A third-party key in the Vite bundle
Vite ships every VITE_ variable to the browser. AI keys and Stripe secret keys belong in a backend function. Base44 can proxy some integration calls so the credential stays on the server. A key pasted into a component skips that.
Check it yourself
Search the live bundle for sk-, sk_live, rk_, and VITE_. A public client id can stay. A secret cannot. Rotate any secret that was in the file.
Medium
A source map next to the static build
Base44 site hosting serves the built files. A source map beside the bundle can include the original components, including a comment or a key you thought was only in the editor.
Check it yourself
Open a published script and look for sourceMappingURL. If the map includes original sources, turn source maps off for the production build and delete the .map file.
Critical
An .env file on a host you run yourself
Base44's own static hosting is unlikely to serve your repo's .env. A custom host will, if that file is in the deployed folder. The free check requests /.env either way.
Check it yourself
Open /.env, /.env.local, and /.git/HEAD on the live domain. You want a not-found page for each.
A prompt you can paste
Paste this into Base44, 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 Base44 app for data that is public and for secrets in the frontend. 1. For every entity that holds private data, set row-level security. Do not leave the rules empty, and do not set read to true unless the records are meant for anonymous visitors. Use a condition such as created_by matching the current user, or a role check. Hide sensitive fields with field-level rules. 2. Use base44.asServiceRole only inside backend functions. Remove it from React components. If a function uses the service role, enforce the same access check in that function. 3. Remove third-party secrets from the Vite app and from VITE_ variables. Call those APIs from a backend function. The browser may keep a public client id, not a secret key. 4. Turn off production source maps. Do not deploy .env or .git. 5. List any secret that was already in the bundle so I can rotate it. Do not print the secret. Do not set a security rule to true so a screen will load.
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.
- Base44 entity rules are not queried. An open entity can be missed, and a locked entity can still sit next to a key in the Vite bundle.
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 Windsurf app secure?Agent edits that ship a secret, loosen a database rule, or publish a source map.
- Is my Bubble app secure?Privacy rules, API Connector secrets, and the Data API admin token.