RLS enabled but no policies (owner locked out)
Not a leak, yet. The table is locked to everyone, and the quick fix people reach for is the leak.
- Severity
- Low
- Who can exploit it
- Nobody, yet
- Found by
- Free RLS check (static) and the full lab check
- Lab proof
- Automatic: the owner-still-reads check
What it is
With RLS switched on and no policies at all, Postgres denies every read and write through the API. Nothing leaks. But the app's own users can't see their data either, so a feature is broken.
It matters because of what usually happens next. Someone asks their AI tool to "make it work", and the fastest change that makes the error go away is using (true), which turns a broken table into PL-001. The other common workaround is putting the service role key into the frontend, which is PL-010.
Example of vulnerable code
Simplified from the patterns we see in AI-built apps. Synthetic: not taken from any real app.
create table public.notes (
id bigint generated always as identity primary key,
user_id uuid not null references auth.users (id) on delete cascade,
body text
);
alter table public.notes enable row level security;
-- ...and no create policy statements for public.notes anywhere
Check it yourself
-- Tables with RLS on and no policies at all
select c.relname as table_name
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public'
and c.relkind = 'r'
and c.relrowsecurity
and not exists (
select 1 from pg_policies p
where p.schemaname = 'public' and p.tablename = c.relname
);
The fix PatchLabs writes
PatchLabs writes the four owner policies the table was missing, so users get their own rows back and nobody else gets anything.
create policy "Owners read own notes" on public.notes
for select to authenticated using ((select auth.uid()) = user_id);
create policy "Owners add own notes" on public.notes
for insert to authenticated with check ((select auth.uid()) = user_id);
create policy "Owners edit own notes" on public.notes
for update to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);
create policy "Owners delete own notes" on public.notes
for delete to authenticated using ((select auth.uid()) = user_id);
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
[BEFORE] owner → 0 rows (locked out) [FIX] add owner policies [PROVE] anon → 0 rows DENIED stranger → 0 rows DENIED owner → 1 row, own OK [DONE] lab proof passed
The owner check is the part of the proof that catches this. A fix that leaves the owner with 0 rows fails, which is also how the lab catches fixes that close a leak by locking everyone out.
When the pattern is intended
RLS on with no policies is the correct setup for a table only your server touches: an audit log, a job queue, or data written by an Edge Function using the service role key. The service role bypasses RLS, and the API roles get nothing, which is what you want.
If your frontend never reads the table, there is nothing to fix. The free RLS check reports it as low severity for that reason.
Supabase linter
- 0008 rls_enabled_no_policy
- Flags the same pattern. Supabase's linter reports it; PatchLabs adds the owner policies and proves the owner can read again.
Related findings
Anonymous visitor can read personal data
Anyone with your app's public key can read emails, phone numbers or addresses.
PL-010Service role key in client code
The key that ignores every access rule, shipped to every visitor's browser.
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-003?
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.