Is it safe that my Supabase anon key is public?
Last reviewed October 15, 2026 against the providers' current documentation.
The short version
Yes, the anon key (and the newer sb_publishable_ key) is meant to be in your browser code. It's only safe if Row Level Security is turned on for every table it can reach. Without RLS, that public key can read and change your data.
Why it matters
The anon key is like your app's street address: everyone can see it. Row Level Security is the lock on each door. Supabase checks every request made with the public key against your RLS policies. If a table has RLS turned off, those checks never happen.
Fix it, in this order
List tables without RLS
In the Supabase dashboard, open the Security Advisor. It flags tables in thepublicschema with RLS disabled. You can also run this in the SQL editor:
Any row withselect tablename, rowsecurity from pg_tables where schemaname = 'public';rowsecurity = falseis open.Turn RLS on for each table
For every table, run:
With RLS on and no policies, the public key can't read anything from that table. That's safe, but your app may stop showing data until the next step.alter table public.your_table enable row level security;Add a policy for what users actually need
The most common case is "users can see their own rows":
Add similar policies for insert, update and delete only where the app needs them.create policy "Users read their own rows" on public.your_table for select to authenticated using ( (select auth.uid()) = user_id );Test as a stranger
Open your app in a private window without logging in and try the pages that load data. Then log in as a second test user and make sure you can't see the first user's rows.
Or ask your AI tool to do it
Paste this into Lovable, Bolt, Cursor, Claude Code or whichever tool built your app. Review what it changes before you deploy.
Audit my Supabase setup. For every table in the public schema, make sure Row Level Security is enabled. Write the minimum policies the app needs: users can only select, insert, update and delete their own rows (matching auth.uid() to the owner column), and anything public must be read-only. Never use the service_role or secret key in frontend code to get around RLS. Give me the SQL as a migration and list which pages use which table.
How this happens
AI app builders create tables quickly and sometimes leave RLS off, or add a policy like using (true) that lets everyone read everything, because it makes the app work on the first try.
Check that it's really fixed
After you deploy, run the free check. It reads your live site the way an attacker would and tells you if any secret key is still visible.
Check my app freeQuestions
RLS is on. Am I safe now?
Only if the policies are right. A policy with using (true) on a table with private data is the same as no lock. Read each policy and ask: who can this let in?
Should I hide the anon key?
There's no need, and you can't anyway: the browser needs it to talk to Supabase. Spend the effort on RLS instead.