Firebase Security Rules · The Short Guide

Firebase Security Rules are the entire security boundary between your users and your database. Firestore and Storage each have their own rules file. The default `allow read, write: if true;` from the getting-started guide is the single biggest source of Firebase data leaks. Deny by default, then open specific paths gated on `request.auth` claims.

Common misconfigurations

  • `allow read, write: if true;` · The getting-started snippet meant for local emulator testing. Search your `firestore.rules` for `if true` before every deploy.
  • Test-mode Storage rules expiring · Firebase Storage rules default to allow-all for 30 days then flip to deny-all. Many teams miss both edges.
  • Ownership check on write but not read · Common mistake · users can read everyone's docs but only write their own. Enforce ownership on both.
  • Trusting client-provided `userId` field · Rules must compare against `request.auth.uid`, never against a field the client sets.
  • Rules that don't fail closed · If no rule matches, Firestore denies. Good. Ensure you don't have a catch-all `if true` that overrides this.

Example

Deny-by-default Firestore rules for a user-owned collection

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // Deny everything by default
    match /{document=**} { allow read, write: if false; }

    // Users can read/write their own notes
    match /notes/{noteId} {
      allow read: if request.auth != null
        && resource.data.ownerId == request.auth.uid;
      allow create: if request.auth != null
        && request.resource.data.ownerId == request.auth.uid;
      allow update, delete: if request.auth != null
        && resource.data.ownerId == request.auth.uid;
    }
  }
}

Frequently asked

How do I test Firebase rules?

Use the Firebase console's Rules Simulator, or run the Firebase Emulator locally with unit tests via `@firebase/rules-unit-testing`.

Are Firebase rules enough on their own?

For Firestore and Storage, yes · they are the security boundary. For Cloud Functions, you still need in-code auth checks.

What's the difference between `request.auth` and `resource.data`?

`request.auth` is the caller's identity. `resource.data` is the existing document. `request.resource.data` is the incoming write.

Scan for this issue →