How to check that Row Level Security is on for every Supabase table
Need to see which Supabase tables are still open? Security Advisor flags public tables with RLS off. Turn it on, then add a policy.
Reviewed October 16, 2026
What it means in plain English
Row Level Security (RLS) is the Postgres switch that decides which rows the API may touch. Supabase's RLS guide says a table in an exposed schema without RLS is readable and writable by any role that has a grant on it. The Data API is exposed to the internet with the publishable key that ships in your app.
Security Advisor names this as lint 0013_rls_disabled_in_public: "Table publicly accessible." The ramification it prints is that anyone with your project URL can read, edit, and delete all data in that table.
Turning RLS on is not the same as writing a policy. After you enable RLS, Supabase says the anon role cannot read or write through the API until a policy exists. Advisor lint 0008_rls_enabled_no_policy is the "no access rules" finding for that case.
Likely causes
- The table was created in SQL or by an agent and RLS was never enabled. Advisor lint 0013 is the flag.
- RLS is on and there is no policy, so the app suddenly gets an empty list or a write error. That is lint 0008, and it is safer than leaving RLS off.
- A view was created by the
postgresuser. Supabase says views bypass RLS by default because Postgres creates them as security definer. A view over a protected table can hand out every row. - The table lives in a schema listed under Exposed schemas in the API settings, so the Data API can see it.
How to fix it, step by step
- In the Supabase dashboard, open Security Advisor. You can also run
supabase db advisorsfrom the CLI. Look for0013_rls_disabled_in_publicon every table you do not intend to be world-readable. - For each table that lint names, enable RLS. In the SQL editor:
alter table public.blog enable row level security;
Replace public.blog with the schema and table from the finding. Supabase's example uses public.blog.
- Reload Security Advisor.
0013_rls_disabled_in_publicshould be gone for that table. If0008_rls_enabled_no_policyappears, the table is locked until you add a policy. Add one policy per operation the app needs. Supabase's example for a signed-in user reading their own rows:
create policy select_own_posts on public.blog
for select
using ((select auth.uid()) = user_id);
Do not copy a policy that uses using (true) for the anon role unless that table is meant to be public.
- Repeat until Security Advisor no longer lists 0013 for the tables in exposed schemas. Then check 0008 and decide, table by table, whether a policy should allow a read or a write.
- If a view sits on top of those tables, do not assume the view is protected. Supabase says a view needs the same attention as a table. See the "Expose a view safely" section of the RLS guide.
- If this project does not use the Data API at all, Supabase's other option for lint 0013 is to remove that schema from Exposed schemas in the API settings. That hides every table in the schema from the API.
Writes that then fail with "new row violates row-level security policy" need an insert policy. See new row violates row-level security policy. An empty list with no error is the matching read symptom: Supabase returns an empty array.
How to check it worked
- Security Advisor does not list
0013_rls_disabled_in_publicfor the tables you checked. - A request that uses only the publishable key cannot read a table you did not write a policy for.
- A signed-in user can still read and write the rows their policy allows.
Security Advisor also flags security definer views, a mutable search_path, and policies that trust user_metadata. See Supabase Security Advisor warnings explained.
Sources
Related fixes
More Supabase RLS and permissions fixes
Keep going on your own.
The guides stay free. A deep leak report is $15. Fix packs are $24, or $49 for all three. There is no done-for-you repair.