Guide

Exposed Supabase keys: what anon vs service_role really means

You built an app with Lovable, Bolt or Replit, it uses Supabase, and now something — a tweet, a scanner, a nervous feeling — is telling you your keys are "exposed." Before you panic: not every exposed Supabase key is a problem. One of them is meant to be public. The other can hand your entire database to a stranger. Here's how to tell which one you're dealing with.

The two Supabase keys, in plain English

Every Supabase project ships with two API keys, and the whole story lives in the difference between them.

The one-line rule

The anon key in your frontend is fine if RLS is on. The service_role key in your frontend is a five-alarm fire.

Why this hits AI-built apps hardest

AI builders scaffold a working app in minutes, but they optimize for "it works," not "it's locked down." Two things go wrong again and again:

If you didn't know these two keys were different, that's not on you — the tools rarely stop to explain it.

What actually goes wrong

When the service_role key is sitting in your bundle, the attack takes no skill at all:

Your frontend service_role key Anyone, in DevTools Your database read · edit · delete

Anyone can open your site, find the key in the downloaded code, and query your database directly with full admin rights. No login, no exploit — just your own key used against you. They can dump every user's personal data, quietly edit records, or delete the whole thing.

// In your frontend code — DANGER const supabase = createClient( "https://xxxx.supabase.co", "eyJhbGci…service_role…aGciOiJ" // ← full admin access, shipped to the browser )

How to tell if you're affected

A few quick things to look at:

The honest catch

Doing this reliably by hand is fiddly. Keys are minified, split across bundles, and telling an anon key from a service_role key by eye isn't obvious — the difference is buried inside the token. It's exactly the kind of thing that's easy to get wrong when you're not sure what you're looking for.

Not sure which key your app is exposing?

Paste your app's URL and our free scan checks it in about 10 seconds — whether a dangerous key or an open database is visible to the public.

Scan your app free →

How to fix it, if you found one

// The service_role key belongs here — server only // e.g. a Supabase Edge Function or your backend API route const admin = createClient( process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY // ← never shipped to the browser )

Supabase's own docs on securing your data go deeper on writing RLS policies if you want the full reference.