What this means
Supabase lint 0013_rls_disabled_in_public is rated ERROR. Supabase's own description is that anyone with your project URL can read, edit and delete all data in the table because row-level security is not enabled. The publishable (anon) key in your app does not limit this. It only identifies the project. RLS is what decides which rows a caller may touch.
Why it happens
- The table was created with SQL or a migration. Tables created that way do not get RLS unless the statement enables it, and generated migrations often leave it out.
- An AI tool hit a row-level security error earlier and resolved it by disabling RLS on the table.
- The table was meant to be temporary or internal, and nobody expected the API to expose it. Every table in an exposed schema is reachable.
- The app worked in testing, so nothing prompted a second look. A table without RLS never produces an error.
How to fix it
- 1List every table in the public schema that has RLS off, using the first query below.
- 2For each table, decide who should read and who should write. Write that down before touching SQL.
- 3Enable RLS and create the policies in one transaction, so there is no moment where the table is locked and your app is broken, or open and exposed.
- 4If a table should never be reached from the browser, enable RLS and add no permissive policy. Your server can still use it with a secret key.
- 5Re-run the security advisor in the dashboard and clear every remaining error.
select schemaname, tablename
from pg_tables
where schemaname = 'public' and rowsecurity = false;
begin;
alter table public.orders enable row level security;
create policy "Customers can read their own orders"
on public.orders for select
to authenticated
using ((select auth.uid()) = customer_id);
create policy "Customers can create their own orders"
on public.orders for insert
to authenticated
with check ((select auth.uid()) = customer_id);
commit;How to confirm the fix
Call your own table through the REST API with only the public key, exactly as a stranger could. Before the fix this returns rows. After the fix it should return an empty array. Then sign in to your app and check that your own data still loads.
curl 'https://YOUR-PROJECT.supabase.co/rest/v1/orders?select=*&limit=5' \
-H 'apikey: YOUR_PUBLISHABLE_OR_ANON_KEY'Frequently asked questions
My anon key is secret, so am I safe?
No. The anon or publishable key ships in your frontend and anyone can read it from the browser. Supabase designs it to be public. Row-level security is the control that protects the data.
Will enabling RLS break my app?
It will block any access you have not written a policy for. That is why you should enable RLS and create the policies together, then test the main flows straight away.
What if I do not use the Supabase API at all?
Supabase notes another option: remove the schema from the exposed schemas in the API settings, which makes everything in it unreachable over the API. Enabling RLS is still a sensible default.
Has my data already been taken?
The advisor cannot tell you. Treat the table as having been readable for as long as RLS was off, review your project's API logs for unfamiliar requests, and consider whether you have a duty to notify users.