Supabase service_role key exposed? What to do in the next 10 minutes
Your Supabase service_role or sb_secret_ key is in your live app's JavaScript. Rotate it, move it server-side, turn on RLS, and confirm it's gone with a free scan.
Why it's an emergency
The service_role key (and the new sb_secret_ key) bypasses Row Level Security. Anyone who opens DevTools on your site can read, change or delete everything in your database. The anon / publishable key is fine to ship; this one isn't.
Step 1: rotate the key now
Deleting it from your code does not invalidate the copy that is already public. Roll or revoke it in Supabase under Project Settings → API keys. See Supabase's API keys docs.
Step 2: move privileged calls server-side
Paste the prompt for your builder:
My Lovable app exposes a Supabase service_role / secret key in the browser. Remove it from all client code and any VITE_ variables, use only the anon/publishable key in the frontend, and move every query that needs elevated access into a Supabase Edge Function with the key stored in Supabase secrets. Then list every place the old key was used.
My Bolt app exposes a Supabase service_role / secret key in the browser. Remove it from all client code and any VITE_ variables, use only the anon/publishable key in the frontend, and move every query that needs elevated access into a server-side function (e.g. a Netlify/Supabase function) reading a server-only env var. Then list every place the old key was used.
My Base44 app exposes a Supabase service_role / secret key in the browser. Remove it from all client code and any VITE_ variables, use only the anon/publishable key in the frontend, and move every query that needs elevated access into a Base44 backend function using a stored secret. Then list every place the old key was used.
My Replit app exposes a Supabase service_role / secret key in the browser. Remove it from all client code and any VITE_ / NEXT_PUBLIC_ variables, use only the anon/publishable key in the frontend, and move every query that needs elevated access into a server route that reads the key from Replit Secrets. Then list every place the old key was used.
My v0 app exposes a Supabase service_role / secret key in the browser. Remove it from all client code and any NEXT_PUBLIC_ variables, use only the anon/publishable key in the frontend, and move every query that needs elevated access into a Next.js Route Handler or Server Action reading a server-only env var (no NEXT_PUBLIC_ prefix). Then list every place the old key was used.
Step 3: turn on RLS on every table
Enable Row Level Security on every table, add policies for what users may read and write, and test with the anon key that a logged-out visitor can't read other users' data.
Step 4: confirm the live build is clean
Redeploy, then run the free scan below. It checks your live page and same-origin JS bundles for both the legacy service_role JWT and new sb_secret_ keys. Also check your old *.lovable.app / *.vercel.app address, not just your custom domain.
Free scan
Passive, public-only, no sign-up. Only scan sites you own or are authorized to scan.
FAQ
Is the Supabase anon key safe to expose?
Yes, if Row Level Security is on for every table. The anon (or sb_publishable_) key is meant for the browser. The service_role (or sb_secret_) key is not.
I deleted the key from my code. Am I safe?
No. Rotate it in Supabase. Old builds, caches and anyone who already copied it still have the old key until it is revoked.
How do I know if my service_role key is in my bundle?
Search your live JavaScript for service_role, sb_secret_ and eyJ (decode any JWT and look for "role":"service_role"), or run the free AppNightGuard scan, which checks your live HTML and JS bundles for both key formats.