How to check in two minutes
Open your live app, open the browser's developer tools, and search the loaded JavaScript for service_role or sb_secret_. Also search your repo for those strings and for any VITE_ or NEXT_PUBLIC_ variable that holds a Supabase key. Only the anon or publishable key belongs in the browser.
git grep -n -i -E "service_role|sb_secret_"
If you find it, rotate first
Assume the key has been copied. Create a new secret key (or roll the JWT secret on older projects) in your Supabase API settings, update it in your server environment, and revoke the old one. Removing it from the code without rotating leaves the old key working.
Not sure which of these it is? We'll tell you in 24 hours, free.
Get a free health checkMove the privileged work to the server
Anything that needed the secret key, such as admin actions or writes that skip user checks, belongs in a Supabase Edge Function, an API route, or a backend job where the key lives in server-only environment variables.
Then lock the tables
Turn on Row Level Security for every table in the public schema and add policies for each action. Run the Security Advisor in your Supabase dashboard to catch tables you missed.
Questions people ask
Is the Supabase anon key a secret?
No. The anon or publishable key is meant to be used in browsers and mobile apps. It is safe only when Row Level Security is enabled with policies on every exposed table.
What happens if my Supabase service role key leaks?
Anyone with it can read, change or delete any data in your project, because it skips Row Level Security. Rotate it right away and move code that needs it to a server.