Multiple Permissive Policies OR'd Together in Supabase
Supabase security checks · MEDIUM
Several permissive policies combine with OR, so the loosest one wins.
What goes wrong
When a Supabase table has several PERMISSIVE RLS policies for the same operation and role, Postgres combines them with OR. If one of them is too broad, it overrides all the others.
How it happens
The policies were written expecting AND logic.
How to find it
Group pg_policies by table, command and roles, and look for more than one PERMISSIVE policy.
SELECT tablename, cmd, roles, array_agg(policyname) AS policies, count(*) AS policy_count FROM pg_policies WHERE schemaname = 'public' AND permissive = 'PERMISSIVE' GROUP BY tablename, cmd, roles HAVING count(*) > 1;
How to fix it
Use RESTRICTIVE policies for the conditions that must always be true. Those are combined with AND.
CREATE POLICY "must_be_owner" ON public.<table_name> AS RESTRICTIVE FOR ALL 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.