← Learn

I leaked my Supabase service_role key — what now?

A exposed service_role key bypasses all your database security. Here is the exact, ordered recovery: rotate, remove, lock down, and check for abuse.

The Supabase service_role key bypasses Row Level Security completely — anyone who has it can read, change, or delete your entire database. If it shipped to the browser (or a public repo), treat it as compromised and act in this order.

1. Rotate it now

In Supabase → Settings → API, regenerate the service_role key. The old one is burned the moment it was public; rotating it is what actually stops the bleeding. Update your server-side environment with the new key.

2. Get it out of client code

Remove every use of the service_role key from anything that runs in the browser, including client-readable env vars (VITE_, NEXT_PUBLIC_, REACT_APP_). The browser should only ever use the anon key.

3. Move privileged logic server-side

Anything that genuinely needs the service_role key (admin actions, bypassing RLS) belongs in a Supabase Edge Function or an API route — called from the client, never embedded in it.

4. Turn on RLS as a safety net

With Row Level Security on, the anon key alone can’t do damage even if something slips.

5. Check for abuse

Review your Supabase logs and table contents for unexpected reads, writes, or deletions while the key was exposed.

→ Scan your app to confirm the key is gone

FAQ

Do I need to rotate the service_role key if I already removed it from my code?
Yes. Once a secret has been public, removing it is not enough — anyone could have copied it. Rotate (regenerate) it so the exposed value stops working.

Where is the service_role key allowed to live?
Only on a server: an Edge Function or API route environment variable. Never in client code or a client-readable env var.

Will turning on RLS protect me?
RLS protects against the public anon key, but the service_role key bypasses RLS entirely — so you must rotate it regardless.

Related questions

Check your own app
Free passive scan, ~10 seconds, no login.