My Supabase API Key Is Exposed: Is That a Problem?
By Pouyan · Updated August 2026
You opened your app's source code, saw your Supabase key sitting right there in plain view, and your stomach dropped. Here's the reassuring-but-important truth: whether that's a real problem depends entirely on which key it is , and for the common case, it's not the key you should worry about, it's a setting behind it.
There are two Supabase keys. Only one is a disaster.
The anon key: public by design
Supabase gives every project a public "anon" (anonymous) key. It is meant to be in your frontend code, that's how your app talks to the database from the browser. Seeing it in your page source is completely normal and not, by itself, a leak.
The anon key being visible is not the bug. The bug is Row-Level Security being off behind it.
The anon key is safe only when Row-Level Security (RLS) is switched on for every table. With RLS on, the key can't read data it shouldn't. With RLS off, that public key lets anyone read the whole table. So the real question isn't "is my key exposed", it's "is RLS on."
The service_role key: never, ever public
The service_role key is the opposite: it bypasses every rule you set. It's the master key to your entire database. It must live only in server-side code (API routes, edge functions) and must never appear in anything the browser downloads. If you find a service_role key in your frontend, that is a genuine emergency, fix it today (steps below).
How to tell which key you're looking at
Both keys are long strings that start with eyJ…. To tell them apart, copy the key and paste it into a JWT decoder (like jwt.io). Look at the role field:
"role": "anon"→ the public key. Normal to be visible; make sure RLS is on."role": "service_role"→ the master key. Must not be public. Rotate it now.
What to do
If it's the anon key
Don't panic and don't bother "hiding" it, you can't, and you don't need to. Instead, confirm Row-Level Security is on for every table and that each table has a sensible policy. That's the actual fix. Our RLS walkthrough shows exactly how.
If it's the service_role key
- In Supabase, go to Settings → API and rotate the service_role key immediately. This invalidates the exposed copy.
- Find where it's used and move it to server-side code only. Never reference it from anything that runs in the browser.
- Assume it may have been used while exposed, check your database logs for unusual activity, and if personal data may have been reached, see what to do after a breach.
Not sure? Just check it
You can work through the list above yourself, and this guide is meant to let you do exactly that. If you would rather have someone look at it, send me your app's address and I will go through it myself before we speak, then tell you what I found in half an hour. It is free, there is no pitch at the end, and if your app is in good shape I will tell you that.
Common questions
Is it safe for the Supabase anon key to be public?
Yes, the anon (anonymous) key is designed to live in your frontend code. It is safe as long as Row-Level Security is switched on for every table, which stops the key from reading data it shouldn't. The key being visible is normal; the danger is Row-Level Security being off behind it.
How do I tell the anon key from the service_role key?
Both are long JWT strings, but if you decode them (paste into jwt.io) the anon key has "role": "anon" and the service_role key has "role": "service_role". The service_role key bypasses ALL your data rules, it must never appear in frontend code. If it does, that's a genuine emergency.
My service_role key was exposed, what do I do?
Treat it as urgent. In your Supabase dashboard, go to Settings → API and rotate the service_role key immediately, then remove it from any frontend code and move it to server-side code only (API routes, edge functions). Anyone who copied it had full, unrestricted access to your database until you rotate it.
How do I check if my data was actually exposed?
Even with the anon key public, your data is only reachable if Row-Level Security is off. Check each table in the Supabase Table Editor for an 'Unrestricted' badge, or have a senior engineer try an anonymous read for you and tell you plainly whether data came back.
Not sure if yours is affected?
Send me your app's address. I'll look at it myself before we speak, then we take half an hour and I'll tell you what I found in normal words. Free, no pitch, and if it's in good shape I'll tell you that too.
Pouyan Ahmadpour · engineer · Amsterdam
Keep reading
- Is My AI-Built App Ready for Real Users? What Breaks First
The parts that only fail on the day you succeed.
- Is My Claude Code App Secure? What Agents Quietly Skip
What the agent built, and what it never mentioned it skipped.
- Is My Lovable App Secure? A Plain-English Safety Check
The checks that matter before you let real users in.
- Supabase Row-Level Security
The single most common way vibe-coded apps leak user data.
- The Vibe-Coding Security Checklist
12 checks between a working prototype and a safe product.
- My Vibe-Coded App Got Hacked
The calm, step-by-step response when the worst has happened.
- Is My Bolt App Secure? The Checks That Matter Before Launch
What to check on a Bolt.new app before real users arrive.
- Is My Replit App Secure? A Plain-English Safety Check
The Replit-specific gotchas, plus the universal checks.
- Firebase Security Rules
The Firebase version of the open-database problem.
- What Does It Cost to Secure a Vibe-Coded App?
What an audit and fixes actually cost, and what you get.