Home / Guides

Supabase "RLS Disabled in Public" warning: how to fix it

Updated 2026-10-14 ยท Defensive guide for your own app

Short answer

The warning means a table in your public schema has Row Level Security turned off. Supabase's own advisor rates it ERROR: anyone with your project URL and public key can read, insert, update and delete every row through the auto-generated API. Fix it by enabling RLS and adding one narrow policy per operation in the same migration. Enabling RLS alone makes the table deny everything, which is safe but will break your app until policies exist.

The fix (SQL)

Run this in the SQL Editor or, better, in a migration. Replace notes and user_id with your table and owner column.

-- 1. Turn on RLS
alter table public.notes enable row level security;

-- 2. Only grant what each role needs (signed-out visitors get nothing here)
revoke all on table public.notes from anon, authenticated;
grant select, insert, update, delete on table public.notes to authenticated;

-- 3. One policy per operation, scoped to the owner
create policy "owner can read" on public.notes for select
  to authenticated using ( (select auth.uid()) = user_id );
create policy "owner can insert" on public.notes for insert
  to authenticated with check ( (select auth.uid()) = user_id );
create policy "owner can update" on public.notes for update
  to authenticated using ( (select auth.uid()) = user_id )
  with check ( (select auth.uid()) = user_id );
create policy "owner can delete" on public.notes for delete
  to authenticated using ( (select auth.uid()) = user_id );

For truly public data (a product catalog, blog posts), grant select only and use a read policy with using (true). Never pair using (true) with write access.

If you don't use the Data API at all (you only connect from a server with a connection string), Supabase notes you can instead remove public from the exposed schemas.

How to check it worked

  1. Open Security Advisor in the dashboard (or run supabase db advisors) and confirm lint 0013 is gone.
  2. List tables still missing RLS:
    select schemaname, tablename
    from pg_tables
    where schemaname = 'public' and rowsecurity = false;
  3. Test as a real user, not from the SQL Editor (which runs as a privileged role). Sign in as user A in your app and confirm you cannot see user B's rows.
  4. Write a pgTAP test with supabase test db, as Supabase's RLS guide recommends, so the policy can't silently regress.

Common mistakes

Check your own project in seconds

Upload a .zip of your own Lovable, Bolt, Cursor, Supabase or Firebase project. ProdCanary reviews the code statically and shows your top 3 risks with plain-English fixes. Your upload is deleted right after the scan.

Run a free scan

FAQ

Is the warning serious if my app looks fine?

Yes. The app working is not the issue; the table being reachable by anyone with the public key is. Supabase classifies lint 0013 as ERROR.

Will enabling RLS break my app?

It can. With RLS on and no policy, the API returns no rows. Ship the enable statement and the policies together and test on a staging project first.

Will new tables get RLS automatically?

Don't assume so. Tables created in raw SQL or by an AI tool's migration may not have it. Supabase's RLS guide covers an event trigger that enables it on every new table; otherwise check with the query above.

Can I hide my anon/publishable key instead?

No. Supabase says publishable keys are meant to be public. RLS and grants are what protect the data.

Sources

This guide is for securing apps you own or are authorised to work on. Facts above are from the official docs linked; check them for changes.