// docs / baas security / firebase if-true explainer
Firebase allow read, write: if true explained: what it does and how to fix it
<code>allow read, write: if true;</code> is the single most common Firebase misconfiguration in production. It is the test-mode default that the Firebase Console suggests when you create a new database, the rule that AI coding tools regenerate from documentation, and the rule that opens your entire Firestore database to anyone on the internet. This article explains the syntax precisely, shows what an attacker sees when this rule is live, and gives you four progressively-stricter replacements that fit different use cases.
The syntax, line by line
A complete Firestore test-mode rules document is six lines:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}Decoded:
rules_version = '2';selects the v2 rules engine (current). Older v1 rules are deprecated.service cloud.firestorescopes the block to Firestore. Realtime Database uses a different JSON-based syntax; Cloud Storage usesservice firebase.storage.match /databases/{database}/documentsbinds the special(default)database (most projects have only one).match /{document=**}is a recursive wildcard. The**matches any path of any depth. Combined with{document}, this captures every document in every collection โ a single match clause governing the entire database.allow read, write: if true;is the rule body. Bothreadandwriteare allowed; the conditionif trueis, well, always true.readcoversgetandlistoperations;writecoverscreate,update, anddelete.
Net effect: any client with the Firebase project ID and the right SDK can read or write any document in any collection. Authentication is not required. Rate limits are not enforced.
Why Firebase ships this as the default
Firebase wants you to be coding in the first 30 seconds after creating a project. The alternative โ making you write a correct rule before any read or write works โ would block onboarding. So the Console offers two options when you create a database: Production mode (deny everything, you write the rules) or Test mode (allow everything for 30 days). Most developers click test mode, then forget to revisit. Older projects had the 30-day timer; current projects have an indefinite if true rule with no automatic expiry.
The structural problem: AI coding tools train on documentation, tutorials, and Stack Overflow answers that show test-mode rules. When you ask Cursor or Claude Code "how do I set up Firebase," the answer often includes the exact allow read, write: if true block as if it were the production rule. The AI does not know โ and is not prompted to know โ that this rule is not safe for production.
What an attacker sees
Concretely, an attacker who knows your Firebase project ID (extractable from any deployed app's bundle in 30 seconds) and runs the following can list every document in every collection:
A single unauthenticated curl request is enough to enumerate every collection. See the highlighted block below.
curl 'https://firestore.googleapis.com/v1/projects/[project-id]/databases/(default)/documents:listCollectionIds' \
-X POST \
-H 'Content-Type: application/json' \
-d '{}'The response is the full list of top-level collections. For each collection, a second request returns documents. There is no rate limit on this path because if true rules accept anonymous traffic. We have seen Firebase databases with millions of documents enumerated in under an hour.
On the write path: a single POST with {fields} creates a new document. Attackers can pollute your collections with garbage, deface user-facing pages that read from Firestore, or use your database as a free message broker โ your usage bill spikes, you investigate, the bill explains the problem.
Four production-safe replacements
Pick the replacement that matches your app's data model. All four assume you have user authentication (Firebase Auth or any provider that issues a Firebase ID token):
Option 1: User-owned documents
Most common SaaS pattern. Documents live under /users/{userId}/... and only the owner can touch them. match /users/{userId}/{document=**} { allow read, write: if request.auth != null && request.auth.uid == userId; }
match /users/{userId}/{document=**} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}Option 2: Owner field on every document
When documents live in flat collections (not nested under user ID), store an owner_uid field and check it. match /posts/{postId} { allow read: if resource.data.public == true || resource.data.owner_uid == request.auth.uid; allow write: if request.auth.uid == resource.data.owner_uid; }
match /posts/{postId} {
allow read: if resource.data.public == true
|| resource.data.owner_uid == request.auth.uid;
allow write: if request.auth.uid == resource.data.owner_uid;
}Option 3: Multi-tenant org isolation
For B2B SaaS with org-scoped data. Store an org_id field on every document and check it against the user's custom claim. allow read, write: if request.auth.token.org_id == resource.data.org_id;. Requires setting the custom claim during sign-up via Firebase Admin SDK.
allow read, write: if request.auth.token.org_id == resource.data.org_id;
Option 4: Read-only public content
For marketing content, public profiles, product catalogs โ anything that is genuinely public-read but admin-only-write. match /products/{productId} { allow read: if true; allow write: if request.auth.token.admin == true; }. The admin custom claim is set on admin accounts only.
match /products/{productId} {
allow read: if true;
allow write: if request.auth.token.admin == true;
}Quick audit query
Before fixing, check whether if true is actually live. Open Firebase Console โ Firestore โ Rules and search for if true. If you find it anywhere outside a comment, you have an open-rule finding. The Rules simulator in the same UI lets you replay the attacker's request locally โ paste an anonymous GET /users/somebody and confirm the simulator returns Allowed.
External confirmation: run a FixVibe scan against your production URL. The baas.firebase-rules check probes your Firestore, Realtime Database, and Storage rules and reports the same finding that an attacker would discover โ independent of what the Firebase Console shows.
Frequently asked questions
What's the difference between <code>if true</code> and <code>if request.auth != null</code>?
if true allows anonymous access โ anyone on the internet. if request.auth != null requires any signed-in user, which is better but still wrong: any user of your app can read every other user's data. Production rules must scope to the specific user or org via request.auth.uid == resource.data.owner_uid or similar.
Does Firebase ever automatically expire <code>if true</code> rules?
Older projects (pre-2023) had a 30-day timer that converted if true rules to if false. Current projects do not โ the rule persists indefinitely until manually replaced. If you created your project before 2023 and your rules look fine, double-check: the timer may have already flipped them to if false, which blocks your own app.
Can I use a future-date timestamp check as a safety net?
No โ a timestamp condition is not a security control. It expires the open rule on a future date, which means until that date attackers have full access. And you will forget the date. Replace if true with an auth-scoped rule, not a time-bounded one.
What if my app is genuinely public-read (blog, product catalog)?
Then explicitly write allow read: if true; allow write: if false; on the public collection only โ not on every collection in your database. Use a separate match clause per collection and never use the recursive {document=**} wildcard on writable rules.
Next steps
Run a FixVibe scan against your production URL โ the baas.firebase-rules check confirms whether if true is currently exploitable from the public internet. For the scanner mechanics and the parallel detections for Realtime Database and Storage, see Firebase rules scanner. For the equivalent class of misconfiguration on Supabase, read Supabase RLS scanner.
