LeakSweep

2026-03-02

The anon key is public. The service role key is not.

A generated app almost always puts a Supabase key in the JavaScript. That is not automatically a leak. Supabase's API keys guide says the publishable key (sb_publishable_...) and the legacy anon key are low privilege and safe to put in a web page, a mobile app, or source code. The secret key (sb_secret_...) and the legacy service_role key are not. They bypass row-level security. The same page says a secret key must not go in a browser, a shipped app, or source control, and that secret keys are rejected with HTTP 401 when used from a browser.

The securing your data guide says a frontend can use the Data API safely only if row-level security is on and policies grant the least access the app needs, and if the client is created with the publishable key. It tells you to treat an older anon key like a publishable key: it identifies the project, it is not a secret, and it still needs those policies. Secret and service-role keys "are never safe to expose because they bypass RLS."

Supabase also says the legacy anon and service_role keys are being deprecated by the end of 2026 in favour of publishable and secret keys. The privilege split does not change. Builders still paste the powerful key into a VITE_ or NEXT_PUBLIC_ variable because a tutorial called every key an API key.

LeakSweep follows that split. A Quick Scan reports a service_role JWT or an sb_secret_ value in the bundle as a critical finding, and it tells you to rotate it. It reports an anon or publishable key as information, not as a stolen password. A Deep Scan then uses only that public key to ask whether tables return a count or fail a write for an authorisation reason. It never uses the secret key to "see how bad it is", because that request would bypass the policies and pull data we have promised not to store.

If you only remember one sentence from Supabase's docs, use theirs: the public key is safe to expose when row-level security is actually on. The secret key is not safe to expose at all.