PL-025criticalCode

Firebase rules allow anyone

Your Firestore, Realtime Database or Storage rules say yes to everyone, or do until a test-mode date.

Severity
Critical
Who can exploit it
Anyone on the internet
Found by
PatchLabs Code: firestore.rules, storage.rules, database.rules.json
Lab proof
Not lab-proven: file and line in the report

What it is

Firebase apps talk to the database straight from the browser, like Supabase apps, and the config in your frontend (apiKey, projectId) is public by design. Security rules decide access. PL-025 means the rules in your repo let anyone in: allow read, write: if true;, a test-mode rule if request.time < timestamp.date(…) that is open to everyone until that date, or ".read": true and ".write": true in Realtime Database.

A rule of if request.auth != null is Firebase's version of PL-002: anyone who signs up passes it.

Why AI builders produce it

Firebase's "test mode" start opens the database for 30 days so you can build without writing rules. Projects ship like that, or someone pushes the date forward when it expires and the app breaks. Generated rules often stop at request.auth != null, because "only signed-in users" sounds like the requirement.

Example of vulnerable code

Simplified from the patterns we see in AI-built apps. Synthetic: not taken from any real app.

firestore.rules (vulnerable)
// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2026, 12, 31);
    }
  }
}

Check it yourself

check-pl-025.sh
# Open rules in the repo
grep -nE "if true|request\.time *<|\.(read|write)\"? *: *true" \
  firestore.rules storage.rules database.rules.json 2>/dev/null

Then test the rules the way an attacker would, against the local emulator. This test seeds one private document and checks that a visitor and a stranger are refused while the owner still reads it:

rules.test.mjs
// rules.test.mjs
// npm i -D firebase @firebase/rules-unit-testing
// run: firebase emulators:exec --only firestore "node rules.test.mjs"
import { readFileSync } from 'node:fs';
import { initializeTestEnvironment, assertFails, assertSucceeds } from '@firebase/rules-unit-testing';
import { doc, getDoc, setDoc } from 'firebase/firestore';

const env = await initializeTestEnvironment({
  projectId: 'demo-rules-check',
  firestore: { rules: readFileSync('firestore.rules', 'utf8') },
});
await env.withSecurityRulesDisabled(async (ctx) => {
  await setDoc(doc(ctx.firestore(), 'users/owner'), { email: 'owner@example.com' });
});

const visitor = env.unauthenticatedContext().firestore();
const stranger = env.authenticatedContext('stranger').firestore();
const owner = env.authenticatedContext('owner').firestore();

await assertFails(getDoc(doc(visitor, 'users/owner')));
await assertFails(getDoc(doc(stranger, 'users/owner')));
await assertSucceeds(getDoc(doc(owner, 'users/owner')));
console.log('visitor and stranger denied, owner reads');
await env.cleanup();

The fix

firestore.rules (fixed)
// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Each user reads and writes only their own profile
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
    // Posts: anyone can read; only the author can write, and can't hand it to someone else
    match /posts/{postId} {
      allow read: if true;
      allow create: if request.auth != null
        && request.resource.data.authorId == request.auth.uid;
      allow update: if request.auth != null
        && resource.data.authorId == request.auth.uid
        && request.resource.data.authorId == resource.data.authorId;
      allow delete: if request.auth != null
        && resource.data.authorId == request.auth.uid;
    }
  }
}

Deploy with firebase deploy --only firestore:rules, and run the test above in CI so the rules can't quietly open up again.

Code findings come with the file, the line and a one-line fix in the report, for your engineer to make. PatchLabs never pushes to your repo.

How PatchLabs finds it

code scan · report excerpt
[SCAN]    firestore.rules:5
          read, write until 2026-12-31 LEAK
[FIX]     owner-only rules
          emulator test in the report
synthetic exampleReport excerpt · read from the repo, not lab-proven

PatchLabs Code reads the rules files in your repo. It never contacts your Firebase project, so rules edited in the Firebase console and never saved to the repo are invisible to it. If you edit rules in the console, copy them back into the repo.

When the pattern is intended

Public reads of public data, such as allow read: if true; on a products collection, are fine. Open writes almost never are.

Why it’s rated critical

Critical: anyone with your public config, which is in your frontend, can read, overwrite or delete the whole database.

Guides

Free check

Does your app have PL-025?

Paste your public repo. PatchLabs Code reads it for this and every other code finding, and the Lab rebuilds your database to test who can read what.

Free for your first appReads your public repo onlyOr run the free static RLS check

Last reviewed 10 Nov 2026. Finding IDs are stable: link to them freely. Spotted a mistake? Tell us.