Guides

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.

Free, one time, and limited to what a stranger can already see. No account required.

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

Free, one time, and limited to what a stranger can already see. No account required.

Other builders

Vibe-coded app security checklist · All guides