Stop 22 of 42 · Account Access · Database access rules (RLS & Firebase rules)

Drawers with no lock rule

Some apps let the browser talk to the vault directly, with no teller in between. The vault door is open to anyone with the public key, which is printed on the lobby wall. The only protection is a lock rule on each drawer. If a drawer has no rule, or the rule says “anyone,” every customer can open every drawer.

Severity High to CriticalCategory RLS MisconfigurationAccount AccessSources checked 25 Oct 2026

Watch it happen

Play it as

Mallory copies the public key from the street and opens every drawer in the vault directly, because the drawers have no lock rule.

Arrival

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.
1 / 5

In bank terms and app terms

In the bankIn your app
Public key on the lobby wallThe Supabase anon key (now called the publishable key) or Firebase config, visible in your website’s JavaScript
Going straight to the vaultThe browser calling the database directly, skipping your API
Lock rule on each drawerRow Level Security policies in Supabase, security rules in Firebase
A rule that says "anyone"USING (true), or allow read, write: if true

Are you exposed?

You might be exposed if…
  • 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.
What to do about it
  1. 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.
  2. In Firebase, replace open rules with owner checks like request.auth.uid == userId, and add validation on writes.
  3. Test as a signed-out visitor and as a second user: you should not be able to read the first user’s data.

Track these in your to-do list →

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.

Prompt
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