How to check if Supabase RLS is enabled on every table
Run this in the Supabase SQL Editor. Any row with rowsecurity = false is a table without RLS.
select schemaname, tablename, rowsecurity from pg_tables where schemaname = 'public' order by rowsecurity, tablename;
pg_tables.rowsecurity is true when row security is enabled on the table. Source: PostgreSQL docs: pg_tables.
List every policy
select schemaname, tablename, policyname, roles, cmd, qual, with_check from pg_policies where schemaname = 'public' order by tablename, cmd;
qual is the USING expression and with_check the WITH CHECK expression. Look for true on private data, and for policies that do not name a role. Source: PostgreSQL docs: pg_policies.
Check grants too
select table_name, grantee, privilege_type
from information_schema.role_table_grants
where table_schema = 'public' and grantee in ('anon','authenticated')
order by table_name, grantee;
Supabase notes that RLS does not remove grants; a table protected only by policies may still give anon an insert path if the grant was never revoked. Source: Supabase docs: Row Level Security.
Enable RLS on a table
alter table public.your_table enable row level security; revoke all on table public.your_table from anon, authenticated; grant select, insert, update, delete on table public.your_table to authenticated;
Once RLS is on and no policy exists, the publishable key can access no rows of that table through the API. Then add one policy per operation. Supabase recommends testing them with pgTAP via supabase test db.
Dashboard options
The Supabase dashboard's Security Advisor flags common problems with the built-in roles (source: Supabase docs: API keys). From the outside, a permission-gated RLS Radar scan shows which tables your public key can query, without downloading rows.
FAQ
Does enabling RLS break my app?
It can: with RLS on and no policies, the publishable key sees no rows. Add policies for what your app needs before deploying.
Do views respect RLS?
Not by default. On Postgres 15+, create views with security_invoker = true so they use the caller's RLS.
Free, read-only, permission-gated. Nothing stored.