Firebase rules checker

Paste your Firestore, Realtime Database or Cloud Storage rules and see every rule that lets a stranger read or write your data, from test mode to auth != null, with the line, the risk and the rule to paste instead.

Runs in your browser. Nothing you paste leaves this page.

Type detected automatically

Rules type
Try an example:

In the Firebase console, open Firestore Database, Realtime Database or Storage, then the Rules tab. In a project, look for firestore.rules, database.rules.json or storage.rules.

Paste your rules to see what a stranger can do.

Firestore, Realtime Database or Storage, detected for you. Each problem comes with its line, the risk and the rule to paste.

  • Rules open to anyone, and test-mode dates
  • “Signed in” checks that any new account passes
  • Owner checks a user can fake with their own data
  • Recursive wildcards and parent rules that override the rest
  • Writes with no check on the data, size or file type

What the Firebase rules checker looks for

Your Firebase config ships in your app's JavaScript, so anyone can send requests straight to your database. Security rules are the only thing between that stranger and your data. The checker reads your rules the way Firebase evaluates them and flags each rule a stranger can get through.

Pattern in your rulesWhat a stranger can doSeverity
allow read, write: if true;, or allow write; with no conditionRead, change and delete data without an accountCritical
request.time < timestamp.date(...), the test mode ruleEverything until the date. After it, the app breaks and the quick fix reopens itCritical, high once expired
request.auth != null as the only checkCreate a free account, then read or edit other users' dataHigh, critical on a catch-all
Owner check on request.resource.data onlyTake over someone else's document by writing their own uid into itHigh
match /{document=**} or /{allPaths=**} with broad accessGet past every stricter rule in the fileHigh or critical
".read": true high in a Realtime Database treeRead everything below it, whatever the child rules sayCritical at the root
Writes with no check on the dataAdd fields your app trusts, like a role or a planMedium or low

Two rules of the Firebase engine explain most findings. In Firestore and Storage, when several match blocks cover the same path, a request is allowed if any one of them allows it, so one broad wildcard cancels everything stricter. In the Realtime Database, .read and .write cascade down: once a parent grants access, a false below it has no effect. Firebase documents the first under overlapping match statements and the second in its list of insecure rules.

How to read the result

The verdict on top names the worst thing a stranger can do with these rules. Each finding gives the line, what that stranger can do, and a corrected rule with a copy button. Click a line number to jump to it in the editor.

  • Critical: anyone on the internet gets in, with no account, or with one any stranger can create. Fix these first.
  • High: a free account or a guessed ID is enough to reach other users' data.
  • Medium: access wider than your app needs, often a public read that may be on purpose.
  • Low: hygiene, such as a missing rules_version = '2' or writes with no data checks.

A public read is not always a bug. Published posts or a leaderboard can be public by design. When the checker can't tell, it says so, and the fix shows how to keep the public part public while only the author writes.

How to fix the common problems

Replace test mode and auth != null with an owner check

The test mode rule and the request.auth != null rule many generated apps switch to next both let strangers in. Tie each document to the user who owns it, by its path or by a field it stores.

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

    // Owner by path: users/{userId}
    match /users/{userId} {
      allow read, delete: if request.auth != null && request.auth.uid == userId;
      allow create, update: if request.auth != null && request.auth.uid == userId
        && request.resource.data.keys().hasOnly(['name', 'photoUrl']);
    }

    // Owner by field: the uid stored in each document
    match /orders/{orderId} {
      allow read: if request.auth != null
        && resource.data.customerId == request.auth.uid;
      allow create: if request.auth != null
        && request.resource.data.customerId == request.auth.uid;
    }
  }
}

Then delete the catch-all block, the match with a recursive wildcard that grants access to every path. Without it Firestore refuses everything by default, and each collection opens only where you wrote a rule for it.

Check the stored owner on updates

request.resource.data is what the client sends. If an update rule only checks the uid there, any user can put their own uid into someone else's document and take it over. Check resource.data, the document as stored, and keep the owner field from changing.

firestore.rules
allow update: if request.auth != null
  && resource.data.ownerId == request.auth.uid
  && request.resource.data.ownerId == resource.data.ownerId;

Realtime Database: grant access at the deepest path

Remove ".read": true and ".write": true from the root and from parent nodes, then compare auth.uid to the key under each user.

database.rules.json
{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        ".write": "auth != null && auth.uid === $uid",
        ".validate": "newData.hasChildren(['name'])"
      }
    }
  }
}

Storage: one folder per user, with size and type limits

storage.rules
match /users/{userId}/{fileName} {
  allow read: if request.auth != null && request.auth.uid == userId;
  allow create, update: if request.auth != null && request.auth.uid == userId
    && request.resource.size < 5 * 1024 * 1024
    && request.resource.contentType.matches('image/.*');
  allow delete: if request.auth != null && request.auth.uid == userId;
}

Roles, custom claims and shared documents are covered in the Firebase security rules guide.

What a static check can't tell you

This tool reads your rules. It doesn't run them, so keep its limits in mind:

  • It can't follow every get() or exists() lookup or see what your documents hold. A condition it can't judge is left alone rather than flagged.
  • It doesn't see which rules are deployed. The console, the CLI and a coding agent can each overwrite them.
  • It doesn't know your app. A public read may be intended, and a strict rule can still leak through a Cloud Function or API route that uses the Admin SDK, which skips rules.

Prove your rules with tests. The Firebase emulator runs them on your machine, and @firebase/rules-unit-testing lets you send the request a stranger would send and assert that it fails.

rules.test.mjs
import { initializeTestEnvironment, assertFails, assertSucceeds } from "@firebase/rules-unit-testing";
import { doc, getDoc } from "firebase/firestore";
import { readFileSync } from "node:fs";

const env = await initializeTestEnvironment({
  projectId: "demo-rules",
  firestore: { rules: readFileSync("firestore.rules", "utf8") },
});
const alice = env.authenticatedContext("alice").firestore();
const stranger = env.authenticatedContext("mallory").firestore();

await assertSucceeds(getDoc(doc(alice, "users/alice")));
await assertFails(getDoc(doc(stranger, "users/alice")));
await env.cleanup();

Run it with firebase emulators:exec --only firestore "node rules.test.mjs". Then test the live app: the rules in production, and every route around them. Your Firebase API key being visible is expected, as the guide on exposed Firebase API keys explains, which is why the rules carry all the weight.

Questions

Is it safe to paste my rules into this Firebase rules checker?

Yes. The check runs entirely in your browser: the rules you paste never leave the page and nothing is stored. Rules are not secret anyway, since anyone with your public config can probe them, but your project's structure stays with you.

What do Firebase test mode rules do?

Test mode creates a rule that allows every read and write until a set date: request.time < timestamp.date(...) in Firestore, now < ... with a timestamp in milliseconds in the Realtime Database. Until that date anyone with your config can read and change everything. After it every client request is refused, and moving the date forward reopens it all.

Is request.auth != null enough in Firebase security rules?

No. It only proves the request comes from some signed-in account, and sign-up is open by default in Firebase Authentication. Compare request.auth.uid to the document's path or to an owner field, so each user reaches only their own data.

Where can I find good Firestore rules examples?

Every fix this tool suggests is a working example for a common case: owner by path, owner by field, shared documents with a members list, and public reads with owner-only writes. The Firebase security rules guide covers roles and custom claims.

Why does ".read": false not work in my Realtime Database rules?

Realtime Database rules cascade down. If a parent node grants .read or .write, every child inherits it and a false below cannot take it back. Remove the grant from the parent and set it on the deeper paths that need it.

Does a clean result mean nobody can get into my data?

No. It means the checker found no open rule in what you pasted. The deployed rules can differ, lookups depend on real data, and server code using the Admin SDK skips rules. Test the rules in the emulator, then check your live app.

More free tools

Your app is public. So are its mistakes.

Check what any attacker can already see in it, free, in ten seconds. The full attack, with proof and fixes: €49 once, or €29 a month on a plan.

or continue with Google or GitHub