Supabase service_role key in your frontend: what to do now
Short answer
If your service_role key (or a new sb_secret_... key) is in client code, treat it as leaked. Supabase's docs say it has the BYPASSRLS attribute, so it skips every Row Level Security policy you wrote. Fix the code first so the key only lives on a server, then create a new secret key, deploy it, and retire the old one. Only the publishable key (sb_publishable_...) or legacy anon key belongs in the browser.
Why it happens
AI builders often wire a privileged key into the client to make a permission error go away. Bundlers then ship it: Vite exposes any variable prefixed VITE_, and Next.js exposes any variable prefixed NEXT_PUBLIC_.
The fix
# .env — browser-safe values only get a public prefix
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
# Server-only. Never prefix these.
SUPABASE_SECRET_KEY=sb_secret_...
// server-only code (route handler, server action, Edge Function)
import 'server-only'
import { createClient } from '@supabase/supabase-js'
export const supabaseAdmin = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SECRET_KEY!
)
Then rotate, following Supabase's order: (1) fix the root cause, (2) create a new secret key under Settings > API Keys, (3) replace it everywhere and confirm, (4) delete the old secret key, or deactivate the legacy JWT keys.
Every server route that uses the admin client must check who the caller is before acting, because RLS no longer protects you there.
How to check
- Search your repo and build output for
service_role,sb_secret_,SERVICE_ROLEand long tokens starting witheyJnext to a Supabase URL. - Check that no env var holding a secret starts with
VITE_orNEXT_PUBLIC_. - Check git history too; deleting the line does not remove an earlier commit. Rotate regardless.
- Review your database logs for unexpected activity during the exposure window.
Check your own project in seconds
Upload a .zip of your own Lovable, Bolt, Cursor, Supabase or Firebase project. ProdCanary reviews the code statically and shows your top 3 risks with plain-English fixes. Your upload is deleted right after the scan.
Run a free scanFAQ
Is the anon key also dangerous?
The anon/publishable key is designed to be public. It is only as safe as your RLS policies and grants.
I removed the key from the code. Am I done?
No. Anyone who loaded the old bundle or read the repo may have it. Rotate the key.
Do new secret keys work in the browser?
Supabase says sb_secret keys are rejected with HTTP 401 when sent from a browser User-Agent, but they still work from other tools, so a leak is still serious.
Where should privileged logic live?
In server code you control: route handlers, server actions or Edge Functions that verify the caller first.
Sources
- Supabase: API keys (incl. rotating a leaked key)
- Vite: Env variables and modes
- Supabase: Row Level Security
This guide is for securing apps you own or are authorised to work on. Facts above are from the official docs linked; check them for changes.