Rules file: test-fixtures/bad.rules
Scanned: 5/9/2026, 10:33:54 PM
Target: /{document=**} (read,write)
The infamous Firebase data leak pattern. `match /{document=**} { allow read, write: if true; }` opens every collection in the database to anyone with the project ID. Common in dev rules left in production.
{
"path": "/{document=**}",
"ops": [
"read",
"write"
],
"condition": "true",
"line": 7
}// firestore.rules — replace catch-all "if true" with explicit deny + per-collection rules:
match /{document=**} {
allow read, write: if false; // explicit default-deny
}
match /users/{uid} {
allow read, write: if request.auth != null && request.auth.uid == uid;
}
match /publicConfig/{doc} {
allow read: if true; // ONLY read, ONLY this collection
allow write: if false;
}
Target: /publicData/{doc} (read,write)
`allow read, write: if true;` always evaluates to true. Anyone with the project ID can read or write this path without auth. Almost always a leftover from local development.
{
"path": "/publicData/{doc}",
"ops": [
"read",
"write"
],
"condition": "true",
"line": 12
}// firestore.rules line 12:
// Replace 'if true' with an explicit ownership check.
match /publicData/{doc} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.ownerId;
}
Target: /users/{uid} (read,write)
`if request.auth != null` lets any signed-up user read/write the document, including anonymous-auth users. Identical to the PocketBase `@request.auth.id != ""` anti-pattern. Tighten with `request.auth.uid == resource.data.ownerId` or similar ownership check.
{
"path": "/users/{uid}",
"ops": [
"read",
"write"
],
"condition": "request.auth != null",
"line": 17
}// firestore.rules line 17:
// 'request.auth != null' lets ANY signed-up user (including anonymous-auth) read/write.
// Add ownership scoping:
match /users/{uid} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.ownerId;
}
Target: /testMode/{doc} (read,write)
`request.time < timestamp.date(YYYY, MM, DD)` is the default test-mode rule Firebase generates. After the date passes, it becomes effectively `if false` (denies everything) — but BEFORE it passes, it's `if true` (open to all). If the date is in the future, this is wide open right now.
{
"path": "/testMode/{doc}",
"ops": [
"read",
"write"
],
"condition": "request.time < timestamp.date(2027, 1, 1)",
"line": 22,
"expiry_date": "2026-12-31",
"currently_open": true
}// firestore.rules line 22:
// Test-mode timestamp rule. EXPIRES 2026-12-31 — currently OPEN.
// Replace with proper auth rules:
match /testMode/{doc} {
allow read, write: if request.auth != null; // tighten further per-collection
}
Target: (end of file)
Firebase denies by default if no rule matches, but having an explicit `match /{document=**} { allow read, write: if false; }` at the bottom is a defensive habit that prevents accidents from rule reorders.
{
"recommendation": "add `match /{document=**} { allow read, write: if false; }` at end"
}// firestore.rules — add at end of service block:
match /{document=**} {
allow read, write: if false;
}
Review each block before deploying. Then: firebase deploy --only firestore:rules
// Wildcard match `/{document=**}` with `if true` — ALL documents publicly readable/writable (/{document=**} (read,write))
// firestore.rules — replace catch-all "if true" with explicit deny + per-collection rules:
match /{document=**} {
allow read, write: if false; // explicit default-deny
}
match /users/{uid} {
allow read, write: if request.auth != null && request.auth.uid == uid;
}
match /publicConfig/{doc} {
allow read: if true; // ONLY read, ONLY this collection
allow write: if false;
}
// Rule contains `if true` literal — bypasses all security checks (/publicData/{doc} (read,write))
// firestore.rules line 12:
// Replace 'if true' with an explicit ownership check.
match /publicData/{doc} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.ownerId;
}
// Rule allows any signed-in user (`if request.auth != null`) without ownership check (/users/{uid} (read,write))
// firestore.rules line 17:
// 'request.auth != null' lets ANY signed-up user (including anonymous-auth) read/write.
// Add ownership scoping:
match /users/{uid} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.ownerId;
}
// Test mode rules: timestamp-based expiry already passed or about to expire (/testMode/{doc} (read,write))
// firestore.rules line 22:
// Test-mode timestamp rule. EXPIRES 2026-12-31 — currently OPEN.
// Replace with proper auth rules:
match /testMode/{doc} {
allow read, write: if request.auth != null; // tighten further per-collection
}
// No explicit default-deny rule — relying on Firebase implicit deny ((end of file))
// firestore.rules — add at end of service block:
match /{document=**} {
allow read, write: if false;
}