Inverted policy logic
What it looks like
create policy "owners only" on invoices
for select using (auth.uid() <> user_id);
-- or, inside a database function:
if auth.role() = 'authenticated' then
raise exception 'not allowed';
end if;What happens
Signed-out visitors or other customers can read rows meant for one account, while the owner sees an empty page and nobody notices.
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
One education app built on Lovable had 16 vulnerabilities, 6 critical; a database function denied callers whose role was 'authenticated', so anonymous callers passed and 18,697 user records were readable without login.
- 16 Vulnerabilities found
- 6 Critical
- 18,697 User records exposed
- 14,928 Unique email addresses
- 870 Enterprise users with full PII
Feb 2026 · Taimur Khan · 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, and read every policy on a table that holds customer data.
- Read each condition aloud as a sentence. It should say who is allowed in, such as "the signed-in user's id equals the row's user id". A condition built on "not equal", "is null" or "raise an error when authenticated" is the warning sign.
- Sign out of your app completely, then open a page that should show only your own data.
- In the dashboard, open Advisors, then Security Advisor, and read every warning about policies and functions.
A bad result is any data appearing while signed out, or a policy whose plain-English reading blocks the owner instead of strangers.
What we check
We call every table and database function three ways: signed out, as a normal account and as a second account, then compare the rows returned with who should see them. The report lists each policy or function where the result is the reverse of its intent.
Fix direction
Rewrite each policy to state who is allowed, comparing auth.uid() with the owner column and adding the TO authenticated clause so anonymous callers stop before the condition runs. Supabase's docs recommend naming the role in every policy and checking that auth.uid() is not null; the Security Advisor flags the most common mistakes.
Mechanism documented in: Row Level Security (verified 2026-09-21); 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
- RLS policy that allows everything with using (true)Data accessCritical
The table looks protected in the dashboard, yet any visitor with the public anon key can read, insert, update and delete every row.
- 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.
- 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.
- 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.
Questions
how do i check if my supabase rls policy is backwards
Read the policy condition as a sentence and ask whether it names who is allowed in. A condition that denies signed-in users, or compares the user id with "not equal", lets the wrong people through. Then sign out and open a page that should be private; if data appears, the policy is not doing what you meant.
why can i see data when logged out of my lovable app
The most common reason is a policy or database function whose condition is the wrong way round, so anonymous callers pass and signed-in users are blocked. In one education app built on Lovable, a function raised an error for authenticated callers and returned user records to everyone else; a researcher reported it in early 2026. Lovable's publish flow warns about tables without RLS, and Supabase enables RLS on dashboard-created tables, but neither reads the logic inside a policy, so run the self-check above.
does rls enabled mean my data is protected
Enabling RLS turns the rules on; the rules themselves still have to be right. A table with RLS enabled and one inverted policy exposes as much as a table with no RLS at all. Supabase's Security Advisor flags disabled RLS and always-true policies, and the three-way test in the self-check catches the inverted ones.
Back to the catalogue, or run the self-check for your stack.