Supabase service_role key exposed? What it means and how to fix it (fast)
· PlugLeak
Found your Supabase service_role key in your frontend? Here's why it's critical, how to check, and the exact steps to rotate it and move it server-side.
Supabase gives every project two kinds of keys. The anon (or sb_publishable_…) key is designed to live in your frontend; it is only safe if Row Level Security (RLS) is enabled on your tables. The service_role (or sb_secret_…) key is different: it bypasses RLS completely. Anyone who has it can read, change or delete every row in your database and every file in storage.
How does a service_role key end up in the browser?
- An AI builder hit an RLS error and "fixed" it by switching the client to the service_role key.
- The key was put in an env var with a public prefix (
VITE_,NEXT_PUBLIC_), which bundlers inline into the JavaScript every visitor downloads. - An admin page or script that uses the key was bundled with the public app.
How to check if yours is exposed
- Open your live app, press F12 → Sources, and search all files for
eyJ(the start of a JWT) andsb_secret_. - For each JWT, paste it into a JWT decoder and look at the
roleclaim.anonis expected;service_roleis an emergency. - Remember to check lazy-loaded chunks, not just the first file — or run the free scan below, which decodes every JWT in every same-site chunk for you. How the scan works covers the file cap and the fact that it does not query your database.
Fix it in this order
- Rotate first. In Supabase → Project Settings → API, roll the service_role / secret key. Removing it from code is not enough: it is already in old bundles, caches and maybe bots' scrapes.
- Move privileged work server-side. Anything that truly needs elevated access goes into a Supabase Edge Function or your backend, reading the key from a server-only secret.
- Use the anon/publishable key in the client and write RLS policies so each user only sees their own rows.
- Check your data. Review the Supabase logs for unexpected activity since the key was first deployed.
Copy-paste prompt for Lovable / Bolt / Cursor
My Supabase service_role key is exposed in the frontend bundle.
1) Remove every use of the service_role key from client-side code and public env vars (VITE_/NEXT_PUBLIC_).
2) Move any operation that needs elevated access into a Supabase Edge Function that reads the key from a server secret.
3) Make the client use only the anon/publishable key.
4) Enable RLS on every table and add policies so users can only access their own rows.
List every file you changed.After rotating and redeploying, re-scan to confirm the old key is gone from every chunk.
Check your app now — free, passive, about 20 seconds.
Same scanner as the homepage scan. Paste the live URL. It reads what a visitor already downloads. It does not log in or query your database.