Guide Supabase
My Supabase anon key is exposed in the frontend. Is that a problem?
Short answer
No, the anon key itself is not the problem. Supabase designed the anon key and its replacement, the publishable key (sb_publishable_), to be visible in your app's JavaScript; anyone can read it, and it only reaches what Row Level Security (RLS) allows. The real question is what your RLS lets that key do. If a table has RLS off, or a policy like using (true) on private data, anyone with the key can read or change it. Rotating the anon key won't fix that. Fixing RLS will. If the exposed key is a service_role or sb_secret_ key, that is a real leak: move it server-side and rotate it.
First: which key is it?
| Starts with | Key | OK in the browser? |
|---|---|---|
sb_publishable_ | Publishable key | Yes |
eyJ, listed as anon | Legacy anon key | Yes |
sb_secret_ | Secret key | No, it bypasses RLS |
eyJ, listed as service_role | Legacy service_role key | No, it bypasses RLS |
Both legacy keys start with eyJ; compare against Settings, then API Keys in your Supabase dashboard. For a secret key, follow Supabase secret key exposed.
Test what a stranger can read (2 minutes)
On your own project only, request a table with just the public key, the way a stranger would:
curl "https://YOUR_PROJECT.supabase.co/rest/v1/profiles?select=*&limit=5" \
-H "apikey: YOUR_ANON_OR_PUBLISHABLE_KEY"
[]or a 42501 error on a private table: good, signed-out visitors can't read it.- Real rows from a private table: anyone on the internet can read them. Fix RLS now.
Don't test in the SQL editor: it runs as the postgres role, which bypasses RLS.
How to fix it
- Open the Security Advisor and fix every "RLS Disabled in Public" error.
- Replace
using (true)on private tables with owner checks such as(select auth.uid()) = user_id. - Grant private tables to
authenticated, notanon. - Re-run the curl test and a two-account test.
Step-by-step for Lovable apps: How to fix Supabase RLS in a Lovable app.
Where we can help
Free instant check: paste your URL at patchandship.com/check.html to scan your homepage's JavaScript for secret keys and security headers (no signup, nothing stored). Paid, fixed price per app: Database Check, $49; Security Fix, $149 (every critical issue on our checklist fixed within 48 hours of working access); Fix & Deploy, $249. Otherwise a full refund if you ask within 14 days of purchase (Refund Policy). AI agents run the checks and a human engineer approves every change. Not a penetration test or a security guarantee.
FAQ
Should I rotate my Supabase anon key?
Rotating it doesn't protect anything if RLS is weak, because the new key also ships in your app. Moving from the legacy anon key to a publishable key is good hygiene, but fix RLS first.
Can I hide the anon key with environment variables?
Not from the browser. A VITE_ or NEXT_PUBLIC_ variable is bundled into the JavaScript every visitor downloads. That's expected for the anon key and never acceptable for a secret key.
A scanner or GitHub alert says my Supabase key leaked. What now?
Check which key it is. An anon or publishable key is a false alarm for the key itself; check RLS. A service_role or sb_secret_ key needs to move server-side and be rotated, then the old key turned off.
Is the anon key the same as the publishable key?
They play the same role. The publishable key (sb_publishable_) is Supabase's newer replacement for the legacy anon JWT.