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
toclause, 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.
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
-- 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.
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
[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 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).
Related findings
Anonymous visitor can read personal data
Anyone with your app's public key can read emails, phone numbers or addresses.
PL-004UPDATE policy missing WITH CHECK
Users may edit their own row, and nothing stops them changing its role, plan or owner.
PL-008Row level security not enabled
No rules at all. With API access granted, anyone with the public key can read and change every row.
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.
Last reviewed 10 Nov 2026. Finding IDs are stable: link to them freely. Spotted a mistake? Tell us.