PL-005high to lowLab

Always-true policy

A policy that says yes to everyone. On writes, anyone can change or delete your data.

Severity
High to low
Who can exploit it
Anyone the policy applies to
Found by
Free RLS check (static) and the full lab check
Lab proof
Automatic for reads; write test included

What it is

using (true) or with check (true) means the policy approves every row for every role it applies to. How bad that is depends on the command:

  • UPDATE, DELETE or ALL: anyone it applies to can change or wipe every row. With no to clause, that includes logged-out visitors. This is the high-severity case.
  • INSERT: anyone can add rows. Fine for a contact form, a problem for an orders or roles table.
  • SELECT: everyone can read every row. Fine for a product list; PL-001 when the table holds personal data.

AI builders often write these as a quick way past a permissions error, usually with names like "Enable update for all users".

Example of vulnerable code

Simplified from the patterns we see in AI-built apps. Synthetic: not taken from any real app.

supabase/migrations/…_orders.sql (vulnerable)
create policy "Enable update for all users"
  on public.orders for update
  using (true);

create policy "Enable delete for all users"
  on public.orders for delete
  using (true);

Check it yourself

check-pl-005.sql
-- Every always-true policy, most dangerous commands first
select tablename, policyname, cmd, roles, qual, with_check
from pg_policies
where schemaname = 'public'
  and (qual = 'true' or with_check = 'true')
order by case cmd when 'ALL' then 0 when 'DELETE' then 1
                  when 'UPDATE' then 2 when 'INSERT' then 3 else 4 end;

The fix PatchLabs writes

PatchLabs replaces each always-true write policy with the narrowest rule the app needs: the row's owner, or staff according to the role table your app already uses.

supabase/migrations/…_patchlabs_fix.sql
drop policy "Enable update for all users" on public.orders;
drop policy "Enable delete for all users" on public.orders;
create policy "Customers update own orders"
  on public.orders for update
  to authenticated
  using ((select auth.uid()) = user_id)
  with check ((select auth.uid()) = user_id);
create policy "Admins delete orders"
  on public.orders for delete
  to authenticated
  using (exists (
    select 1 from public.user_roles r
    where r.user_id = (select auth.uid()) and r.role = 'admin'
  ));

Every fix arrives as a migration file (plus any code change it needs, noted in the report) for your engineer to approve. Download it, or commit it on GitHub in one click from the report page. Automatic pull requests need our GitHub App, which is coming.

The proof it runs

lab proof · public.orders
[READS]   anon      → 0 rows        DENIED
          stranger  → 0 rows        DENIED
          owner     → 1 row, own    OK
[WRITES]  anon update → 0 rows   DENIED
          owner update own → 1 row OK
reads provenWrites: test SQL in the report · fake rows

Reads by the anonymous visitor, a signed-in stranger and the owner are proven automatically on every check. For write policies, the report includes the update and delete tests as SQL for your engineer to run; they are not yet part of the automatic proof.

When the pattern is intended

Always-true is correct in two common cases:

  • select ... using (true) on data meant for everyone: products, blog posts, opening hours.
  • insert ... with check (true) on a contact form or waitlist, as long as nothing lets the public read those rows back.

The report marks these as intended with its reasoning, and you can confirm them so they don't alert again.

Supabase linter

0024 permissive_rls_policy
Flags always-true policies on UPDATE, DELETE, INSERT and ALL. It deliberately skips SELECT, which is where personal-data reads leak (see PL-001).

Guides

Free check

Does your app have PL-005?

Paste your public repo. We rebuild the database from your migrations, test it as a visitor, a stranger and the owner, and hand you the proven fix.

Free for your first appReads your public repo onlyOr run the free static RLS check

Last reviewed 10 Nov 2026. Finding IDs are stable: link to them freely. Spotted a mistake? Tell us.