RLS policy that allows everything with using (true)
What it looks like
alter table public.profiles enable row level security;
create policy "Enable access for all users"
on public.profiles
for all
to anon, authenticated
using (true)
with check (true);What happens
The table looks protected in the dashboard, yet any visitor with the public anon key can read, insert, update and delete every row.
Where it shows up
Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.
Seen in public
A scan of 1,645 Lovable-built apps found 170 (about 10.3%) with database endpoints readable without login because Supabase row-level security policies were missing or too broad; recorded as CVE-2025-48757, CVSS 9.3.
- 1,645 Apps scanned
- 170 Apps with inadequate RLS
- 10.3% Share of scanned apps
- 303 Exposed endpoints
- 9.3 Critical CVSS 3.1 base score (CVE record)
- 8.26 Researcher's own CVSS base score
- 2025-03-21 Scan date
- 2025-05-29 Public disclosure
May 2025 · Matt Palmer (Replit, Inc.) · all sources
Check it yourself
Uses your builder's dashboard and your browser. No tools to install.
- In the Supabase dashboard open Authentication, then Policies. Row Level Security (RLS) is the per-row access rule set Postgres applies to each query, and this page lists every policy per table.
- Click each policy and read the USING and WITH CHECK expressions. Look for
true, or for names likeEnable access for all usersorallow all. - Open Advisors, then Security Advisor, and look for the finding
Permissive RLS Policy. - A bad result is a policy on a table with private data whose expression is
trueforanonorauthenticated, especially for insert, update or delete.
What we check
We read every policy expression from the database catalog and then test each table as an anonymous visitor and as two unrelated signed-in users, confirming whether user A can read or change user B's rows. The report pairs each permissive policy with the rows it exposed.
Fix direction
Replace using (true) with a condition that ties the row to the caller, such as auth.uid() = user_id, and keep true only for data meant to be public and only for select. Supabase's documentation says the same, and its Security Advisor flags always-true policies after each change.
Mechanism documented in: Row Level Security (verified 2026-09-21); Database Advisors (verified 2026-09-21).
Covered by
Pre-launch check ($490, 48 hours) and Security sweep ($290, 24 hours)
Both include a re-check after your fixes.
Related patterns
- Row Level Security disabled on a tableData accessCritical
Anyone with the project URL and the public anon key, both of which sit in the app's JavaScript, can read, edit or delete every row in the table.
- Any signed-in user can read every rowData accessCritical
Anyone who creates a free account can page through every other customer's records, which is a data breach with a sign-up form as the only step.
- Inverted policy logicData accessCritical
Signed-out visitors or other customers can read rows meant for one account, while the owner sees an empty page and nobody notices.
- Record ids accepted without an ownership checkData accessCritical
Anyone who changes the id in a URL or request can read, edit or delete another customer's record.
Questions
what does using true mean in a supabase policy
The USING expression decides which existing rows a query may see or touch, and true means every row passes. Supabase's documentation describes a policy with to anon using (true) as granting unauthenticated visitors read access to all rows and says to use it only for data meant to be public. For private data, the expression should compare the row to auth.uid().
is rls enabled with a permissive policy still protecting my data
No. Enabling RLS only makes Postgres consult the policies; a policy that always returns true then lets everything through. The table shows as protected in the dashboard while behaving as if RLS were off. The Security Advisor lists this as a Permissive RLS Policy finding.
how do i write a supabase rls policy for user owned rows
Create separate policies per operation. For select, use using (auth.uid() = user_id); for insert, use with check (auth.uid() = user_id); for update, use both. Grant them to the authenticated role only. Then sign in as two different test accounts and confirm each sees only its own rows.
Back to the catalogue, or run the self-check for your stack.