Fix.

Your Supabase service role key is in your frontend. Do this now

If that key shipped to the browser, every security policy you have is bypassed. The fix, in order.

5 min read

Supabase gives you two kinds of key. One is meant for the browser. The other bypasses row level security entirely, on every table, for anyone holding it.

If the second one is in your frontend code, it does not matter how good your policies are. It is the master key, and it is sitting in a file anyone can open.

This is not rare. It happens because a query failed, the secret key made it work, and the error went away.

Confirm it in 60 seconds

On your deployed site, open developer tools with F12, go to the Sources panel and search the loaded files for service_role. Then search for eyJ, which is how these tokens begin.

Also search your own code, including any file that sets environment variables. In a Vite build, anything prefixed VITE_ is deliberately shipped to the browser. A secret key with that prefix is a public key.

If you find it in either place, assume it is public. Search engines, archive services and scrapers have all had the chance to read it.

Fix it in this order

1. Rotate the key first. In your Supabase dashboard, under API keys, roll the service role key. This invalidates the exposed one immediately. Do this before anything else, because until it is done every other step is cosmetic.

Rolling it breaks whatever was using it. That is the point, and it tells you exactly what depended on it.

2. Find what broke. Whatever now fails is what was relying on the key. Usually it is one of three things: an admin screen, a data import, or a query blocked by a policy that nobody wanted to write.

3. Move that work to the server. The secret key belongs only where visitors cannot read it: a Supabase edge function, an API route on your host, or a backend service. The browser calls your function, your function uses the key. Nobody downloads it.

4. Write the policy you avoided. If the key was covering for a missing policy, now is when you write it. A policy that compares the logged-in user’s id to the row’s owner column covers most cases.

5. Check what was reachable while it was out. Look at your Supabase logs for requests you cannot account for. Any table that holds personal data and was exposed may trigger a notification duty under GDPR or similar rules. That is a decision to make deliberately, not one to skip.

Stopping it coming back

  • Keep secrets out of any variable your build tool exposes to the browser. Prefix rules exist for a reason.
  • Never let a build succeed with a secret key in frontend code. A simple check that fails the build on finding service_role in the bundle takes ten minutes to write.
  • When a query fails, treat it as a missing policy, not a missing key. That instinct is the whole difference.

The wider check

An exposed secret key usually travels with other things. It is worth checking, in the same sitting, whether row level security is on for every table, whether any policy simply allows everything, and whether a logged-out browser can read data. Those four together are what an audit actually covers.

About the author

Adeola Ilori founded Adeola Forge and leads its engineering work. The studio builds and fixes web apps, AI-built apps and automations.

More articles on fix

Have a project in mind?
Let's build it.

Whether you are building a new SaaS platform from scratch, launching a mobile product, designing a high-conversion interface, or need an urgent rescue for an AI-built app, we are ready to help. You will receive a clear scoped plan and milestone timeline within 1 to 2 business days.

100% code ownership/Direct founder access/Fixed milestones
WhatsApp us