---
title: "Firebase rules left open"
slug: firebase-rules-left-open
severity: critical
category: Database
summary: "Firestore or Storage rules that allow any read and write make the database public. The client SDK will do whatever the rules allow."
platforms:
  - Firebase
  - Next.js
updated: "2026-10-13"
related:
  - supabase-tables-without-rls
  - open-storage-buckets
  - auth-checked-only-in-the-ui
---

Firebase security rules are the access control for Firestore, Realtime Database, and Cloud Storage. The client SDK is not a sandbox. If the rules say yes, the client can do it, including a client someone else wrote.

The usual mistake is test mode. The Firebase console offers rules that allow reads and writes until a date, or people replace that with `allow read, write: if true` so the app keeps working. Both are public databases. `if request.auth != null` is the next mistake: any signed-in user can read every document, which is [IDOR](/issues/idor) for the whole project.

Firebase App Check is an extra that tries to confirm requests come from your app. It is not a replacement for rules. A modified client can still present as a user if the rules allow that user to read everything.

The Firebase web config in your JavaScript is expected to be public. Rules are what make that safe.

## How to check in 5 minutes

1. Open Firestore rules and Storage rules in the Firebase console, and open `firestore.rules` and `storage.rules` in the repo if they exist. Search for `if true` and for dates that only expire access.
2. In the rules playground, or with a second test user, read a document you do not own. If it succeeds, the rules are too open.
3. Check that writes cannot set their own `admin: true` or `plan: "pro"`. A rule that only checks `request.auth != null` allows that write.
4. Confirm the rules you are reading are the ones deployed. A file in the repo can be stricter than the console, or the other way around.

## How to fix

### Firebase

Scope each collection to the owner, and block fields the user must not set.

```
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /notes/{noteId} {
      allow read, update, delete: if request.auth != null
        && request.auth.uid == resource.data.userId;
      allow create: if request.auth != null
        && request.auth.uid == request.resource.data.userId;
    }
  }
}
```

That is a starting shape for one collection, not a full ruleset. Add rules for every collection the app uses. Collections without a match are denied by default when rules are otherwise defined. Do not add a final `match /{document=**} { allow read, write: if true; }` to be helpful.

Deploy with the Firebase CLI so the repo and the project match. Run the rules emulator tests if you have them. Firebase documents the rules language and the emulator in its security rules docs.

Storage needs its own file. See [open storage buckets](/issues/open-storage-buckets).

### Next.js

If an Admin SDK service account is used on the server, rules do not apply to that SDK. Check the session in the Route Handler, the same as a Supabase secret key. Never import the service account into client code.

### Supabase

This bug is the Firestore version of missing RLS. If you use Supabase instead, follow [tables without row level security](/issues/supabase-tables-without-rls).

### Vercel

Hosting on Vercel does not deploy Firebase rules. Deploy them with Firebase. The web app being on Vercel changes nothing about the database.

## Agent prompt

```text
You are closing open Firebase rules. Do not add features.

1. Read firestore.rules, storage.rules, and any realtime database rules. Also tell me if the repo has no rules files, because the deployed console rules may differ.
2. Remove allow read, write: if true and any time-limited test rule.
3. For each collection the app uses, require request.auth.uid to match the owner field on read, create, update, and delete.
4. Prevent clients from setting admin, role, or plan fields unless you can show an existing server-only path. If you cannot, deny those field changes.
5. Do not treat App Check as the access control.

Show the rules diff. Do not claim the console is updated unless you actually deployed.
```

## FAQ

### Test mode expired and the app broke. Can I turn it back on?

That expiry is what stopped the public database. Write an owner rule instead of extending open access.

### The Firebase apiKey is in the source. Do I rotate it?

The web API key is not a secret in the way a service account is. Firebase documents the client config as something your app ships. Rules are the control. Rotate a service account if that JSON leaked. Do not publish the service account to hide the apiKey.

## Sources

- [Firebase security rules](https://firebase.google.com/docs/rules)
- [Firestore security rules getting started](https://firebase.google.com/docs/firestore/security/get-started)
