AppInspected

Supabase security check: what your live app gives away

Paste the address of any app that uses Supabase. We read its JavaScript the way a stranger would, decode every Supabase key we find, and tell you whether the one that skips Row Level Security is in there. Free, about 20 seconds, no sign-up.

Free. No sign-up. We only read what your visitors' browsers already read.

Passive and read-only. Works with any public site, including apps built with Lovable, Bolt, v0, Replit, Cursor, Windsurf and Claude Code.

AppInspected
App
Waiting for your address
Checked
–
Critical issues
–
Not checked yet
Your result fills in this tag. Nothing is stored.

Two things decide whether a Supabase app is safe

Most apps built on Supabase talk to the database straight from the browser. That's how Supabase is designed to work, and it means two things carry all the weight:

  1. Which key is in the browser. Supabase has public keys (the sb_publishable_ key and the legacy anon key) and secret keys (the sb_secret_ key and the legacy service_role key). Supabase's documentation says the public ones are safe to put in a web page, and that secret keys bypass Row Level Security and belong on a server only.
  2. Whether Row Level Security protects every table. With a public key, the only thing between a stranger and your data is RLS: it has to be on for each table the API can reach, with policies that say who may read and change which rows.

The first is visible from outside, so our free check tests it on your live app. The second lives inside your project, so it needs the Supabase dashboard or a test with real accounts. This page covers both.

What the free check looks for in a Supabase app

service_role key: critical
Legacy Supabase keys are tokens that start with eyJ and carry a role inside. We decode each one we find. A service_role token in your page or scripts can read, change or delete every row, whatever your policies say.
sb_secret_ key: critical
The newer secret key does the same job and skips RLS in the same way. Supabase rejects secret keys sent from a browser, but that doesn't protect a leaked one: anyone can use it from a script.
anon or sb_publishable_ key: fine
Expected in a Supabase app and marked Fine, with a reminder that it's only safe when RLS is on. You don't need to rotate it.
Other secrets near your Supabase code
OpenAI, Anthropic, Stripe, Resend and other secret keys that belong in a Supabase Edge Function rather than in the page.
Exposed files and source maps
/.env (where a secret key often sits next to the public one), /.git/HEAD and downloadable source maps.
HTTPS and security headers
HSTS, Content-Security-Policy, framing protection and X-Content-Type-Options.

We read your page plus up to 25 JavaScript files from your own domain, including the code chunks they load. The check is passive: we never send a request to your Supabase project, never sign in and never use a key we find. Keys in the result are cut down to their first and last few characters.

Example result

Example free check result: two critical findings (a Supabase service_role key and a Stripe secret key in the JavaScript, both shown cut short), and a medium finding for public source maps, each with a link to a step-by-step fix guide.
A made-up app with a Supabase service_role key and a Stripe secret key in its JavaScript. Each finding links to the fix.

How to check your Row Level Security

A clean free check means no secret key is leaking. It can't tell you whether your tables are protected, because RLS isn't visible from a web page. Three ways to find out, from quickest to most thorough:

  1. Run Supabase's Security Advisor

    In the Supabase dashboard, open Advisors → Security. It lists problems such as a table in public with RLS off, a table that has policies but RLS switched off (so the policies do nothing), a policy that allows everything, a view that runs with its creator's rights, and policies that trust user_metadata, which users can edit themselves. Fix the errors first.
  2. Look at the tables yourself

    Every table in an exposed schema needs RLS on. With RLS on and no policies, the public key gets nothing back. Add one policy per operation, limited to the row's owner, for example using ((select auth.uid()) = user_id). Step by step: Supabase RLS disabled.
  3. Test as a stranger and as a second user

    Open your app in a private window without signing in, then sign in as a second test account, and try to load the first account's data. If either one sees it, a policy is too wide.

The $19 website security report can do the last two for you. After you prove you own the site, it reads your app the same way as the free check but much further (up to 30 pages and 40 scripts), and adds an optional Supabase section: you create two test accounts and a test record, and we run read-only tests to see whether a signed-out visitor or the other account can read it. You can also paste your Security Advisor output (you fetch it yourself; we never need your Supabase access token) to get every lint explained in plain English with the SQL to fix it.

A Supabase change coming on October 30, 2026

Supabase is changing how new tables reach its Data API. Per its changelog, new tables in the public schema will no longer be exposed to the REST and GraphQL APIs automatically: you'll grant access explicitly, then enable RLS and add policies. The new behavior became the default for new projects from May 30, 2026, and reaches all existing projects by October 30, 2026. Tables that already exist keep their current grants, so this doesn't fix any table that is open today. Check those now.

If the check finds a secret key

  1. Create a new secret key

    In Project Settings → API Keys, create a new secret key. Supabase recommends a separate secret key for each backend component, so a future leak means rotating only one. Guide: Supabase service_role key exposed.
  2. Move the work to a server

    Whatever needed admin rights goes in a Supabase Edge Function, an API route or your backend, with the key in a server-only environment variable (never VITE_, NEXT_PUBLIC_ or EXPO_PUBLIC_). The browser keeps only the publishable or anon key: Is the Supabase anon key safe?.
  3. Turn the leaked key off

    Once the new setup works, delete the leaked secret key or deactivate the legacy service_role key. Removing it from your code isn't enough: copies of your old JavaScript are already out there.
  4. Check the data, then run the check again

    Look for rows, users or files you don't recognize, then paste your address above to confirm the key is gone.

Or ask your AI tool to do it

Paste this into Lovable, Bolt, Cursor or whichever tool built your app. Review what it changes before you deploy.

Do a Supabase security review of this app and report back before changing anything. 1) List every Supabase key used in frontend code or in VITE_/NEXT_PUBLIC_/EXPO_PUBLIC_ variables and say whether it is a publishable/anon key (fine in the browser) or a secret/service_role key (must move to a Supabase Edge Function or API route and be read from a server-only secret). 2) List every table in the public schema with its Row Level Security status, its grants for anon and authenticated, and its policies. 3) Propose a migration that enables RLS on every table, revokes grants the app doesn't need, and adds one policy per operation limited to the row's owner with (select auth.uid()). Never use user_metadata in a policy. Then fix the items I approve, one at a time.

After launch

Website security report

$19 one time

For any website you own: a read-only review of up to 30 pages and 40 JavaScript files (found through your build manifest, routes and sitemap), app logic in the browser (admin and paid-feature checks, prices sent from the browser, AI APIs called directly), headers, cookies and CORS, domain and email records, libraries with known vulnerabilities, forgotten files and third-party scripts, with fixes written for your host. Optional database tests for Supabase or Firebase. Requires proof you own the site.

Get the report See an example report

Badge + daily monitoring

$9 per month

We repeat the outside checks every day and email you when something changes, such as a Supabase secret key or another secret appearing in your JavaScript, a removed header or a certificate about to expire. Includes a live badge and one full website report every 30 days.

How monitoring works

Sources

Questions

Is it safe that my Supabase key is visible in my app?

If it's the anon key or an sb_publishable_ key, yes: Supabase designs those to be public. It's safe only when Row Level Security is on for every table they can reach. If it's a service_role or sb_secret_ key, no: treat it as stolen and replace it.

How do I tell which Supabase key is in my code?

New keys say it in their prefix: sb_publishable_ is public, sb_secret_ is secret. Legacy keys are long tokens starting with eyJ; the middle part names the role (anon or service_role). The check above decodes them for you.

Can this check test my RLS policies?

The free check can't: it never contacts your Supabase project. Use Supabase's Security Advisor, or add the optional Supabase tests to the website security report, which run read-only tests with two test accounts you create.

Does the check send requests to my Supabase database?

No. It only reads your website and its JavaScript, plus a few ordinary requests for files like /.env. It never uses a key it finds.

Supabase blocks secret keys in the browser. Is a leaked one still a problem?

Yes. Supabase returns an error when a secret key is sent from a browser, but its documentation notes that an attacker can still use the key from other tools. Delete or deactivate any key that was public.

Does it work with Lovable, Bolt and other AI app builders?

Yes. It checks the deployed app, so it works for any app that uses Supabase, on a lovable.app or bolt.host address, Vercel, Netlify or your own domain. See also the Lovable security check.

Does it check Firebase too?

It recognizes Firebase web keys, which are public by design. What protects a Firebase app is its security rules; see Firestore test mode rules.

More free checks and guides