Your Supabase service_role key is in your frontend. Here's what to do.
Last reviewed October 15, 2026 against the providers' current documentation.
The short version
Treat it as stolen. Create a new Supabase secret key, move every call that needs it to your server, then turn the old key off. Removing it from your code alone doesn't help, because the old key keeps working until you turn it off.
Why it matters
The service_role key (and its newer replacement, the sb_secret_ key) belongs to a database role that skips every Row Level Security policy. Anyone who opens your site can copy it from the JavaScript and read, change or delete every row in every table, including other users' data.
Fix it, in this order
Confirm it's really the service_role key
Supabase's legacy keys are long strings starting witheyJ. The middle part of the key (between the two dots) says which role it is. If it containsservice_role, it's the dangerous one. New-style keys are easier:sb_secret_…is dangerous,sb_publishable_…is fine. Our free check decodes this for you.Create a new secret key
In the Supabase dashboard, open Project Settings → API Keys and create a new secret key. Supabase now recommends these over the legacy service_role key, and switching to them avoids the downtime that rotating the legacy keys causes.Move the work to the server
Find every place your app used the leaked key. Anything that needs admin rights has to run on a server: a Supabase Edge Function, a Next.js API route or server action, or your backend. Put the new secret key in that server's environment variables, never in a variable the browser can read (VITE_…,NEXT_PUBLIC_…,EXPO_PUBLIC_…).Use the publishable key in the browser
Your frontend should use only the publishable key (sb_publishable_…) or the legacy anon key. Both are designed to be public, as long as Row Level Security is on for your tables.Deploy, then turn off the leaked key
Deploy the fixed app and confirm it works. Then, on the same API Keys page, deactivate the legacy service_role key (or delete the leaked secret key). Do this only after the new setup works, because the change takes effect immediately.Check whether anyone used it
Look at your tables for rows you don't recognize, missing data, or new admin users, and check the API logs in the Supabase dashboard for unusual activity. If you store personal data and see signs of access, you may have legal duties to notify users; ask a lawyer where you operate.
Or ask your AI tool to do it
Paste this into Lovable, Bolt, Cursor, Claude Code or whichever tool built your app. Review what it changes before you deploy.
My Supabase service_role key was exposed in frontend code. Find every place the app uses the service_role or secret key. Move each of those operations into a server-side function (Supabase Edge Function or an API route), read the key from a server-only environment variable, and make the frontend call that function instead. The browser must only use the publishable/anon key. Do not put the key in any VITE_, NEXT_PUBLIC_ or EXPO_PUBLIC_ variable. Then list the tables the frontend reads or writes so I can check their Row Level Security policies.
How this happens
It usually starts with a permission error. The app can't read a table because Row Level Security blocks it, and the quickest fix an AI tool finds is to swap in the key that ignores those rules. It works instantly, so it ships. The real fix was a Row Level Security policy that lets each user see their own rows.
Check that it's really fixed
After you deploy, run the free check. It reads your live site the way an attacker would and tells you if any secret key is still visible.
Check my app freeQuestions
Is it enough to delete the key from my code and redeploy?
No. Copies of your old JavaScript stay in browser caches, search engine caches and anyone's downloads. The key itself must be turned off in Supabase.
Will my users get logged out?
Switching from the service_role key to a new secret key is designed to avoid downtime, and secret keys aren't the tokens your users log in with. Rotating the project's legacy JWT secret is a different, bigger step: Supabase says it immediately invalidates the existing keys and cuts connections until you deploy new ones. Avoid that path unless you need it.