Supabase
Supabase anon key: is it safe to expose?
Yes. The anon key is public by design and is meant to ship in your frontend. It is not the thing that exposes your data. A table with Row Level Security switched off is.
Anon key in your frontend bundle: expected. Every Supabase app works this way, which is why the variable is named NEXT_PUBLIC_SUPABASE_ANON_KEY.
service_role key in your frontend bundle: a real incident. That key ignores RLS completely. Rotate it now and audit what was reachable.
What the anon key actually is
The anon key is a JWT that identifies your project and carries the anon role. Anyone can read it out of any Supabase app, including the official examples. Treating it as a credential to hide misunderstands the model: it is closer to a public project identifier than to a password.
Every request it makes is evaluated against Row Level Security. With RLS enabled and policies written, the key can only reach the rows you allowed. With RLS off, or enabled but with no policy on a table, it can reach whatever that table holds.
anon vs service_role
| anon | service_role | |
|---|---|---|
| Subject to RLS | Yes | No, bypasses it entirely |
| Safe in frontend | Yes, by design | Never |
| If it leaks | Not an incident on its own | Rotate immediately |
The question worth asking instead
Not “is my anon key exposed” but “what can my anon key reach”. Those have very different answers, and only the second one can hurt you. The failure we see most often in AI-built apps is a table that works perfectly in development because RLS was never switched on, then ships that way.
Note that enabling RLS without writing policies denies everything rather than allowing everything, so a table that still returns rows to the anon key either has RLS off or has a policy that is broader than intended.
Test what your anon key can read
vas reads the Supabase config out of your live frontend the same way anyone else can, then queries every table, storage bucket, RPC function, and edge function using your public anon key, and reports what came back. Your first scan is free.
Common questions
Is it safe to expose the Supabase anon key?
Yes. The anon key is designed to be public and ships in your frontend bundle by convention, which is why Supabase names the environment variable NEXT_PUBLIC_SUPABASE_ANON_KEY. It identifies your project and carries the anon role. It is not a secret, and rotating it does not fix a data exposure. What decides whether your data is safe is whether Row Level Security is enabled with policies on every table that key can reach.
What is the difference between the anon key and the service_role key?
The anon key carries the anon role and is fully subject to Row Level Security. The service_role key BYPASSES RLS entirely and can read and write every table regardless of policy. The anon key belongs in your frontend. The service_role key must never leave your server. If a service_role key is in your client bundle, treat it as a breach: rotate it immediately and audit access.
Someone found my anon key in my JavaScript bundle. Have I been hacked?
No, not on its own. Anyone can read the anon key from any Supabase app's frontend, including Supabase's own examples. Finding it proves nothing about your security. The question that matters is what that key can actually do: if RLS is off or a table has no policy, that key can read the table. Test it rather than assume.
Should I rotate my anon key?
Rotating the anon key rarely accomplishes anything, because the replacement is equally public. If data was readable before rotation it will be readable after, since the exposure came from a missing policy rather than from the key. Rotate the service_role key if it ever leaked. Fix RLS if a table was readable.
How do I check what my anon key can read?
Use the key the way an attacker would. In the Supabase SQL editor you can switch to the anon role and SELECT from each table. To test the deployed app instead of the schema, vas reads the Supabase config out of your live frontend and queries every table, storage bucket, RPC function, and edge function with your public anon key, then reports exactly what came back.
Find out what is readable before someone else does
Point vas at your live app. We use the same public anon key anyone can read from your bundle and tell you exactly which tables, buckets, and functions answer.