How to find exposed Supabase keys on your website (and tell the safe one from the dangerous one)
Short answer: search your live site's JavaScript for supabase.co, sb_publishable_, sb_secret_ and eyJ, or run a free SniffPup scan (SniffPup is a free passive security scanner for vibe-coded apps) to do it for you. A publishable or anon key is meant to be public. A secret or service_role key bypasses Row Level Security and must be replaced now. Only check sites you own.
Home › Guides › Find exposed Supabase keys · Last updated · By Ember, SniffPup
The fast way: a free SniffPup scan searches your HTML and same-origin JavaScript for Supabase sb_secret_ keys and for JWTs whose role is service_role, and marks either one critical (masked in the report). If it finds only the public key, it uses it for a read-only check of whether an anonymous visitor can read rows in up to 8 tables (no rows downloaded). No signup.
A 100 means no issues were found in our checks. It is never proof of security.
1. Know the four Supabase keys
Per Supabase's API keys docs, a project can have four kinds of key. Two are meant for browsers and two must never reach one:
- Publishable key (
sb_publishable_...): safe to expose in a web page. It runs as theanonrole (orauthenticatedonce a user signs in), so it reaches only what grants and RLS allow. - anon key (a long JWT starting with
eyJ): the legacy version of the publishable key. Same rules. - Secret key (
sb_secret_...): server-only. It maps toservice_role, which bypasses every RLS policy. - service_role key (also a long JWT starting with
eyJ): the legacy version of the secret key. Same danger.
Supabase says it is deprecating the legacy anon and service_role keys by the end of 2026, so newer apps usually ship a publishable key.
2. Search what your live site actually ships
Look at the published site, not your editor: that's what a stranger loads. Three ways, easiest first:
- DevTools search: open your site, open DevTools, then Customize and control DevTools › More tools › Search to search every loaded file. Search for
supabase.cofirst (it sits right next to the key in most apps), thensb_secret_,sb_publishable_andeyJ. - Network tab: reload the page with the Network tab open and filter for
supabase. Requests toyour-project.supabase.cocarry the key in theapikeyrequest header. - Public files: also open
https://your-site/.envand look for.mapfiles next to your JavaScript. You want a 404 for/.env; a public source map can show your original code, keys and all. The .env exposure checker and source map checker explain both.
3. Tell which key you found
- Starts with
sb_publishable_: the public key. Go to step 5. - Starts with
sb_secret_: a secret key. Go to step 4 now. - Starts with
eyJ: a legacy JWT. Decode the middle part (between the two dots) on your own computer and read therolefield."role":"anon"is the public key;"role":"service_role"is the secret one. With Node.js installed:
node -e "console.log(Buffer.from(process.argv[1].split('.')[1], 'base64url').toString())" "PASTE_THE_eyJ_KEY"Don't paste a key that might be secret into an online decoder or an AI chat. A signed-in user's session token is also an eyJ JWT (role authenticated); that one belongs to whoever is signed in, not to your site's code.
4. Found a secret or service_role key? Replace it now
Anyone who loaded your site can read, change or delete every row. Remove the key from your frontend code and environment variables first (anything in a VITE_, NEXT_PUBLIC_ or similar browser variable ships to visitors), so the next deploy doesn't publish a fresh copy. Then follow Supabase's own order: create a new secret key, switch every server and Edge Function to it, confirm nothing uses the old one, then delete the old secret key (or deactivate the legacy keys). The step-by-step version is in leaked Supabase service_role or secret key: what to do.
5. Found only the public key? Check what it can reach
The public key is only as safe as your tables. Per Supabase's Securing your API docs, grants decide which tables a role can reach and RLS decides which rows. Check that RLS is on for every table in public, then ask for one row of a table that should be private, signed out. The Supabase RLS checker guide has the SQL and the one-line request, and is the Supabase anon key safe? explains when RLS alone is enough.
6. Check your other keys too
Supabase is rarely the only key in a vibe-coded app. Stripe, OpenAI and other provider keys turn up in the same JavaScript bundles. The exposed API keys guide covers the rest, and a free SniffPup scan checks them all at once. For a full audit of the database side, see the Supabase security audit guide.
FAQ
How do I find the Supabase key on my website?
Open your live site, open the browser's DevTools and search all loaded files for supabase.co, sb_publishable_, sb_secret_ and eyJ (the start of a legacy JWT key). Or watch the Network tab: requests to your-project.supabase.co carry the key in the apikey header. A free SniffPup scan does the search for you across your HTML and same-origin JavaScript and masks what it finds.
Which Supabase key is safe to have on my website?
The publishable key (sb_publishable_...) and the legacy anon key. Supabase's docs call the publishable key safe to expose in a web page, because it only reaches what table grants and Row Level Security allow. The secret key (sb_secret_...) and the legacy service_role key are never safe in a browser: they bypass Row Level Security.
How do I tell a legacy anon key from a service_role key?
Both are long JWTs that start with eyJ. Decode the middle part (between the two dots) on your own computer and read the role field: "role":"anon" is the public key, "role":"service_role" is the secret one. Don't paste a key that might be secret into an online decoder.
I found a service_role or sb_secret_ key in my JavaScript. What now?
Treat it as leaked. Remove it from the frontend code first, so the next deploy doesn't ship a new copy, then follow Supabase's steps: create a new secret key, switch every server to it, confirm nothing uses the old one, then delete the old secret key or deactivate the legacy keys. Then check your data for changes you didn't make.
My site only ships the anon key. Am I safe?
Only if your tables are. The anon or publishable key can read and write whatever your grants and Row Level Security allow anonymous visitors to. Check that RLS is on for every public table and test a private table signed out. SniffPup's free scan does a read-only check of up to 8 tables with the public key your site ships (no rows downloaded).
Does a clean SniffPup report mean no Supabase keys are exposed?
No. A score of 100 means no issues were found in our checks. It is never proof of security: the scan sees what your live site serves to a visitor, not your repo, your server code or pages behind a login.
Sources: Supabase's API keys and Securing your API docs and Chrome's DevTools search docs, checked October 28, 2026.
A score of 100 means no issues were found in our checks. It is not proof that your app is secure.