Supabase RLS Not Working? Fix Leaks Between Users (2026)
You sign up with a second test account, open the dashboard, and there they are: the first account’s notes, orders or messages. Or a user emails you a screenshot of someone else’s invoice. RLS is “on”, the builder said the database was secure, and yet one user can see another user’s rows.
That’s the worst bug a small app can ship. If you searched for Supabase RLS not working, here’s the good news: it’s almost never Supabase being broken. The cause is nearly always one of a short list of holes: RLS off on one table, a policy that says using (true), rows with no owner, a secret key in the wrong place, a view or function that skips RLS, or a public storage bucket. This guide shows you how to find which one you have and the copy-paste SQL to close it. New to RLS? Start with the Supabase RLS explainer for the basics, then come back here to fix the leak.
Quick answer: If Supabase users can see other users’ data, check five things in order: RLS is enabled on every exposed table, no policy uses using (true) or only checks the role, every row has a user_id set to auth.uid(), no secret or service_role key runs in the browser, and views use security_invoker = true.
| What you see | Most likely cause | Check | Fix |
|---|---|---|---|
| Every user sees every row | RLS disabled on the table | pg_tables.rowsecurity is false | Enable RLS and add owner policies |
| Signed-in users see all rows, signed-out see none | Policy is to authenticated using (true) | List policies in pg_policies | Replace with (select auth.uid()) = user_id |
| New rows show up for everyone, or for nobody | user_id is null or never set | Count rows where user_id is null | Add default auth.uid() and backfill |
| A user can move a row to another account | UPDATE policy has no WITH CHECK | Read the policy definition | Add with check on insert and update |
| RLS works in tests, leaks in the app | Secret or service_role key in the frontend or a function | Search the bundle and functions for the key | Use the publishable key, rotate the secret |
| Table is safe, a view or rpc() leaks | View or function runs as its owner | Security Advisor 0010 and 0028 | security_invoker views, invoker functions |
| Anyone with a link can open files | Public storage bucket | Bucket settings | Private bucket plus storage.objects policies |
Want it fixed for you? Launch Mango moves your Lovable, Bolt, v0 or Cursor app onto your own GitHub, Supabase and Vercel accounts and makes it safe for real users. Own and Secure is $199 one-off: everything in Own Your App plus sign-in and redirects, Supabase RLS and permissions locked down, exposed API keys removed, live Stripe payments and webhooks, a security report and your custom domain included. Not sure how exposed you are? Run the free 2-minute app check.
Why Can Users See Other Users’ Data in Supabase?
Because something lets a request reach rows its policies should hide. Postgres checks grants first, then RLS policies, and any gap in either one leaks data. The usual gaps are RLS turned off, a policy that allows every row, rows with no owner, a key that bypasses RLS, or a view, function or bucket that skips it.
