github

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.

Check my project