Skip to content
Back to Blog

I think I exposed my Supabase anon key. What now?

Eliott Reich, founder of TaskBounty4 min read
security
supabase
vibe coding
ai dev tools

You spotted your Supabase anon key in your app's JavaScript, or someone pointed out it is sitting in a public GitHub repo, and now you are wondering how bad this is. The short version: the anon key being visible is not, by itself, the problem. What matters is whether your database is protected behind it. Let us walk through it calmly.

The anon key is meant to be public

Supabase gives your project two keys. The service_role key is a full-access secret and must never leave your server. The anon key is different. It is designed to ship in the browser, because your frontend needs it to talk to Supabase. Every visitor to your app already has it. Finding it in your bundle is expected, not a breach.

So if you exposed only the anon key, take a breath. You have not handed anyone a master key.

When it actually is a problem

The anon key is a public identity, not a permission. What decides whether a visitor holding that key can read or write your data is Row Level Security (RLS). RLS is the per-table rule set that says who is allowed to see which rows.

If RLS is turned on and your policies scope rows to the right user, the anon key can do almost nothing on its own, which is exactly the design. If RLS is off, or a table has no policy, the anon key can read (and sometimes write) every row in that table. That is the real leak, and it is by far the most common one we see in AI-built apps. The exposed key is only a headline because the table behind it was left open.

How to check in a couple of minutes

  1. Open your Supabase dashboard, go to the Table Editor, and look at the RLS status on each table. A table with RLS disabled is readable by anyone with the anon key.
  2. For tables that have RLS enabled, open the Policies view and read each policy. A policy of true, or one that does not reference auth.uid(), may still allow everyone through.
  3. To prove it to yourself from the outside, you can point a plain HTTP request at your project's REST endpoint using the anon key and see what comes back. If a table you expected to be private returns rows, RLS is not protecting it.

What to do right now

  • If you find an open table, enable RLS on it and add a policy that scopes rows to the owning user. Treat the data as public until you have done this.
  • Rotating the anon key is usually not necessary and does not fix anything on its own, because the replacement key is just as public. Fix the table rules instead. (If you also exposed the service_role key, that is a different story: rotate it immediately and audit for any misuse.)
  • If the key was in a public repo, still fix RLS first. The key in git is only dangerous to the extent your tables are unprotected.

The fastest way to know

Reading policies by hand is a good habit, but it is easy to miss a table. Our Supabase RLS check uses your app's own published anon key, the same one your app ships to every browser, and tries to read your tables from the outside. If a table returns rows, you know RLS is not protecting it. It is read-only, never logs in, and never writes.

If the check finds an open table and you would rather not fix it yourself, we can close it and prove the fix in a reviewable pull request. Our App Security packages start at $149 to verify your access boundaries, with a full refund if we miss a confirmed issue. The point is to move from "I think I exposed something" to "I know exactly what is exposed and it is closed."

Related