Drawers with no lock rule
Watch it happen
Mallory copies the public key from the street and opens every drawer in the vault directly, because the drawers have no lock rule.
The bank’s public key hangs on the wall outside. That is normal: the key ships inside your website so the browser can talk to the database.
Mallory says: I’ll take a copy of that key.In bank terms and app terms
| In the bank | In your app |
|---|---|
Are you exposed?
You created Supabase tables but never ran ALTER TABLE … ENABLE ROW LEVEL SECURITY, or a policy says USING (true). Your firestore.rules or storage.rules contain "allow read, write: if true" or only check that a user is signed in. Your app works in the browser with the public Supabase key alone, and you have never tried reading other users’ rows with it.
Enable RLS on every table, and write policies that compare the row’s owner to auth.uid(). Keep the service_role key out of the browser: it bypasses RLS entirely. In Firebase, replace open rules with owner checks like request.auth.uid == userId, and add validation on writes. Test as a signed-out visitor and as a second user: you should not be able to read the first user’s data.
What it looks like in code
See RLS Policy Analyzer for detailed fix examples with proper Supabase RLS policies.
Ask your AI tool to fix it
Paste this into Cursor, Claude, Lovable, Bolt or whatever you build with.
Review all Supabase migrations and Firebase rules in this project. Enable row level security on every table, remove any USING (true) or WITH CHECK (true) policies unless that data is meant to be public, and write per-operation policies that compare the row’s owner column to auth.uid(). For Firebase, replace "allow read, write: if true" with owner-based rules using request.auth.uid. List every table or path you changed.Where this comes from
The facts, figures and fixes on this page were checked against these sources on 25 Oct 2026. They are linked so you can check for yourself.
- Row Level SecuritySupabaseEnable RLS on exposed tables; policies compare owner to auth.uid(); no policy means no rows
- API keysSupabasePublic key is safe in browsers only with RLS; the secret key bypasses RLS
- 5.9. Row Security PoliciesPostgreSQLRLS enabled with no policy is default-deny; owners and BYPASSRLS roles skip it
- Fix insecure rulesFirebase'allow read, write: if true' and signed-in-only rules are insecure
- Basic Security RulesFirebaseOwner-only rules with request.auth.uid == userId
- Securing your dataSupabaseEnable RLS on tables the frontend reads; anon key is public but only safe with RLS
Spot a mistake or something out of date? Report a correction · How these guides are made and checked
The free, open-source scanner checks for most of the problems in these guides.