Is your Supabase secret key in your website? How to check and fix it
Only the publishable key (sb_publishable_…, or the older anon key) belongs in your website. If the secret key (sb_secret_…) or the older service_role key is in your frontend code, anyone can copy it from their browser and get full access to your database, skipping every Row Level Security rule. To check, search your live site's code for sb_secret_ and for the last characters of your service_role key. To fix it, move that code into an Edge Function, then replace the key.
Which Supabase keys are safe in the browser?
| Key | Looks like | In your website? |
|---|---|---|
| Publishable | sb_publishable_… | Yes. It's designed for this. |
| anon (older) | Long, starts with eyJ | Yes |
| Secret | sb_secret_… | Never |
| service_role (older) | Long, starts with eyJ | Never |
Supabase is phasing out the older anon and service_role keys by the end of 2026. If you still use them, it's a good moment to move to the new keys.
How the key ends up in the website
When a database query fails because of a security rule, a quick "fix" is a key that skips the rules. That's a common shortcut in AI-built apps, often through a setting called something like VITE_SUPABASE_SERVICE_ROLE_KEY. Anything whose name starts with VITE_ or NEXT_PUBLIC_ is copied into the code every visitor downloads.
Supabase now refuses the newer secret keys when they're sent from a web browser: it checks the browser's User-Agent and returns 401. So with the new keys, a leaked secret key usually breaks the app rather than working quietly. Don't rely on that. Anyone who copies the key can still use it from any other tool.
How to check your live site (5 minutes)
- Open your live site in Chrome, press F12 and choose the Sources tab. Reload the page so every script loads.
- Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search all scripts, and search for
sb_secret_. - If you use the older keys, copy the last 10 characters of your service_role key from Supabase (Project Settings → API Keys) and search for those. Both older keys start the same way, and they're encoded, so searching for the words "service_role" won't find anything.
- While you're there, search for other secret keys: Stripe's
sk_live_,sk_test_andrk_live_, OpenAI'ssk-proj-and Anthropic'ssk-ant-. A leaked AI key means strangers can run up your bill.
How to check your code
- Search the project for
service_role,SERVICE_ROLEandsb_secret_. Each match should be in server code (Edge Functions), never insrc/. - List every setting that starts with
VITE_orNEXT_PUBLIC_. None should hold a secret. - If a real
.envfile was ever pushed to a public GitHub repo, treat every key in it as leaked, even if you deleted it later.
How to fix it
- Move the code. Anything that needs elevated access goes into a Supabase Edge Function that checks who the user is first.
Fix prompt for Lovable or Bolt
"Remove every use of the Supabase secret or service_role key from the frontend. The browser client must use only the publishable (anon) key. Move anything that needs elevated access into a Supabase Edge Function that verifies the signed-in user first. Remove the key from every VITE_ or NEXT_PUBLIC_ setting."
- Fix the rules. Once the browser only has the publishable key, your Row Level Security rules do all the protecting. Check them with our RLS guide.
- Replace the key. A key that was public has to be treated as stolen, even after you remove it from the site. For the newer keys, create a new secret key in Settings → API Keys, update your Edge Functions to use it, then delete the old one. If you're on the older JWT keys, follow Supabase's guide to moving to the new keys and then deactivate the old ones.
- Check it worked. Repeat the live-site search: the old key and
sb_secret_shouldn't appear. Then use the app as a normal user to make sure everything still works. - Look for damage. If the key was public for a while, check your users and data for anything you didn't add. If personal data may have been seen, you may have legal duties to report it (for example under GDPR), so get advice.
Questions
Is the Supabase anon key a secret?
No. The anon key and the newer publishable key are designed to be in your website. Row Level Security is what protects your data from people using them.
My app stopped working after I removed the service_role key. Why?
Some queries were relying on skipping the security rules. Add Row Level Security policies that allow what each user legitimately needs, or move those queries into an Edge Function that checks who the user is first.
Can I use the secret key in a Supabase Edge Function?
Yes. Edge Functions run on Supabase's servers, not in the visitor's browser. Keep the key in the function's environment secrets, never written into the code, and check who the caller is before doing anything with it.
Does Supabase block secret keys used in the browser?
For the newer secret keys, yes: Supabase returns 401 Unauthorized when it detects a browser. That doesn't protect a leaked key, because anyone who copies it can use it from other tools. A leaked key must still be replaced.