RLS Disabled on Public Tables in Supabase
Supabase security checks · CRITICAL
Row level security is off, so anyone holding your public anon key can read and change every row in this table.
What goes wrong
A Supabase table in the public schema without row level security (RLS) is open to anyone who has your anon key. They can read, insert, update and delete every row. The anon key ships in your frontend JavaScript by design, so anyone who opens browser DevTools can see it.
How it happens
Only tables made in the Dashboard Table Editor get RLS switched on automatically. Tables created through the SQL Editor, migrations, ORMs like Prisma or Drizzle, or the Supabase CLI do not, and AI code generators almost always use SQL or migrations.
Real-world impact
CVE-2025-48757 covered more than 170 Lovable apps exposed this way.
How to find it
List the tables in the public schema where rowsecurity is false and the anon or authenticated role still has privileges. With those grants revoked, the Data API can’t reach the table.
SELECT tablename
FROM pg_tables
WHERE schemaname = 'public'
AND NOT rowsecurity
AND (
has_table_privilege('anon', format('%I.%I', schemaname, tablename), 'SELECT,INSERT,UPDATE,DELETE')
OR has_table_privilege('authenticated', format('%I.%I', schemaname, tablename), 'SELECT,INSERT,UPDATE,DELETE')
);How to fix it
Enable RLS on the table, then add policies for the access your app needs. RLS with no policies denies all access, so add the policies in the same change.
ALTER TABLE public.<table_name> ENABLE ROW LEVEL SECURITY; CREATE POLICY "Users can read own <table_name>" ON public.<table_name> FOR SELECT TO authenticated USING ((SELECT auth.uid()) = <user_id_column>);
Check your own project
Locksoup runs these checks on your Supabase database in about a minute, with a read-only role, and gives you the SQL to fix what it finds.