Skip to content
BuildThenTestedSee packages
CriticalData access

Any signed-in user can read every row

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. Rules that decide which user can read or change which rows in the database. Check it yourself with the steps below; our test adds what a script and a second account can find.

What it looks like

create policy "Authenticated users can view orders"
  on public.orders
  for select
  to authenticated
  using (auth.role() = 'authenticated');
A policy that checks the caller is logged in but never checks whose row it is, so every account sees every order.

What happens

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.

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.

  1. 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 shows each policy's expression.
  2. For each table holding private data, read the USING expression. Look for auth.role() = 'authenticated', auth.uid() is not null or true with no reference to a column such as user_id or owner_id.
  3. Create two test accounts in your live app. Sign in as the first, create a record, sign out, sign in as the second, and try to open the first account's record through the app or by changing the id in the address bar.
  4. A bad result is a policy that checks only for a login, or a second account that can see the first account's record.

What we check

We sign in as several unrelated test users, enumerate every table and storage bucket each can list, and compare the results across accounts to find rows that belong to someone else. The report shows the table, the policy text and the cross-account rows reached, with personal data redacted.

Fix direction

Add an ownership condition to each policy, such as auth.uid() = user_id, or a membership check through a team table for shared data. Keep a login-only policy only for content every customer is meant to see. Supabase's Security Advisor and the two-account test above catch regressions after each change.

Mechanism documented in: Row Level Security (verified 2026-09-21); Avoid insecure rules (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.

Compare packages

Related patterns

Questions

supabase rls policy for authenticated users only is that enough

Only for data every customer is allowed to see. A policy that checks auth.role() = 'authenticated' confirms the caller has an account and nothing more, so every account reads every row. For per-customer data, the expression needs to compare a column on the row, such as user_id, with auth.uid().

how do i test if users can see each other's data

Create two test accounts in your live app. Add a record with the first, then sign in as the second and try to open that record through the app and by editing the id in the address bar. Also check the Network tab in the browser's developer tools for list requests that return more rows than the second account created. Any cross-account view is a finding.

firebase rule allow if request auth is not null

Firebase's own documentation lists a rule that only checks request.auth != null under rules to avoid unless you have confirmed that every logged-in user should have access to that data. For private data, compare request.auth.uid with an owner field on the document. Firebase's emulator lets you test the rule with different users before deploying.

Back to the catalogue, or run the self-check for your stack.