Supabase service_role key exposed? What to do in the next hour
If your Supabase service_role key (or a new-style sb_secret_… key) is in your site's JavaScript, a public repo or a screenshot, treat it as stolen. Unlike the anon key, it skips Row Level Security entirely: anyone who has it can read, change and delete every row in every table, every file in Storage, and every user account. Here is what to do, in order.
1. Confirm where it leaked
The usual ways it gets out in apps built with Lovable, Bolt or Cursor:
- A
VITE_orNEXT_PUBLIC_variable. Anything with those prefixes is copied into the JavaScript every visitor downloads. See why VITE_ variables aren't secret. - The AI tool used it to "fix" a permission error, swapping the anon key for the service_role key in
createClient. - A committed
.envfile in a public GitHub repo, or in its history.
To check your live site: open it, press F12, go to Sources (Chrome) or Debugger (Firefox), search all files for service_role and sb_secret_. A legacy key is a long JWT starting with eyJ; paste it into our key checker and it tells you whether it is the anon or the service_role key, in your browser, without sending it anywhere.
2. Move the code that needs it to the server
Revoking the key breaks whatever used it, so first move that code into a Supabase Edge Function (or your own server), where the key stays secret, and make the browser call the function instead. Then make the frontend use only the anon or sb_publishable_ key.
3. Revoke the leaked key
If you use the new API keys (sb_secret_…): in the Supabase dashboard, open Project Settings → API Keys, create a new secret key, put it in your Edge Function secrets, then delete the leaked one. Nothing else changes.
If you use the legacy JWT keys (service_role starting with eyJ): you can't revoke just that key. Either switch to the new publishable and secret keys and then disable the legacy keys, or rotate the project's JWT secret, which also replaces the anon key and signs every user out. Switching to the new keys is usually less disruptive.
Removing the key from your code or Git history does not fix the leak on its own. Copies already exist. Only revoking it does.
4. Check whether anyone used it
- In Logs, look at API requests from the time the key went public for traffic you don't recognise: bulk reads of tables, deletes, or calls to the auth admin endpoints.
- Check Authentication → Users for accounts you didn't create, and Storage for files you didn't upload.
- Check your important tables for missing or changed rows, and restore from a backup if needed.
- If personal data may have been read, you may have to tell your users or your data protection authority, depending on where you and they are.
A prompt to paste into Lovable, Bolt or Cursor
My Supabase service_role key is exposed in the frontend. Fix it:
1. Find every place the service_role or sb_secret_ key is used in
frontend code or VITE_ / NEXT_PUBLIC_ variables and list them.
2. Move each operation that really needs it into a Supabase Edge
Function that checks the user is signed in and allowed to do it,
and reads the key from Edge Function secrets.
3. Make the frontend use only the anon / publishable key, and make
it work through Row Level Security policies instead of bypassing them.
4. Do not disable RLS or loosen policies to make things work.
Show me the changes before applying them. I will revoke the old key
in the Supabase dashboard myself.
Once it is fixed, LeakPatrol's free scan reads the JavaScript your live site loads and flags service_role, sb_secret_ and other secret keys in about a minute, so you can confirm it is gone.
Check your app in a minute
Free, read-only, no sign-up. Every problem comes with a plain-English fix and a prompt for your AI tool.
Get the 10-point checklist
Every check we run on AI-built apps, with how to do each one yourself. Straight to your inbox.
Plus an email when automatic re-checks launch, and the odd tip. Unsubscribe any time.
Questions
What happens if my Supabase service_role key is exposed?
Anyone who has it bypasses Row Level Security and can read, change and delete every row in every table, every file in Storage, and manage user accounts. Treat it as stolen and revoke it.
Is removing the key from my code enough?
No. Anyone who already copied it can keep using it. You have to revoke it in the Supabase dashboard, after moving the code that needs it to an Edge Function.
How do I rotate a legacy Supabase service_role key?
A legacy JWT service_role key cannot be revoked on its own. Switch to the new publishable and secret API keys and disable the legacy keys, or rotate the JWT secret, which also changes the anon key and signs all users out.
Is the Supabase anon key safe to expose?
Yes, the anon or publishable key is meant to be public, but only if Row Level Security is on with correct policies for every table. The service_role and sb_secret_ keys must never be in the browser.
More guides
- Supabase RLS policy generator (free)
- Is this API key safe in my frontend? Free key checker
- Security scan MCP server for Claude Code, Cursor and other AI agents
- Supabase's October 30 change: what it fixes for your app's security, and what it doesn't
- Supabase "42501 permission denied for table": the safe fix (not GRANT ALL)
- Supabase "new row violates row-level security policy": 5 causes and the safe fix
- Lovable security check: is your Lovable app safe?
- Bolt.new security check: is your Bolt app safe?
- Launch checklist for apps built with Lovable, Bolt and Cursor
- Supabase security check: is your anon key safe? (RLS checker)
- How to check if your API key is exposed on your website
- Are VITE_ env variables secret? How to hide API keys
- Stop users giving themselves your paid plan (Supabase)