AppInspected

Fix guides

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

  1. List tables without RLS

    In the Supabase dashboard, open the Security Advisor. It flags tables in the public schema with RLS disabled. You can also run this in the SQL editor:
    select tablename, rowsecurity
    from pg_tables
    where schemaname = 'public';
    Any row with rowsecurity = false is open.
  2. Turn RLS on for each table

    For every table, run:
    alter table public.your_table enable row level security;
    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.
  3. Add a policy for what users actually need

    The most common case is "users can see their own rows":
    create policy "Users read their own rows"
    on public.your_table for select
    to authenticated
    using ( (select auth.uid()) = user_id );
    Add similar policies for insert, update and delete only where the app needs them.
  4. 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 free

Questions

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.

Sources

Related guides