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.

Would rather just talk? Book a call without filling this in. Bring your app's address and we'll look at it together.

Free · 30 minutes · no signup · no card

Pouyan Ahmadpour · engineer · Amsterdam

Keep reading