GUIDESEPISODES
Firebase test mode left open? Lock your rules
You picked “test mode” on day one. Thirty days later the app broke, so you set the rules to let everyone in. Now anyone with your project ID can read every user’s data. Here are the three rules that lock it, and the two-minute test that proves a stranger gets “denied”.

01THE HAUNTING
The drawers that open by themselves
Why it mattersThe lock was never on. The 30-day timer was the only thing that would have closed it.
Here’s how it happens. You start a Firebase project and the console asks you to pick a mode. You pick test mode, because you just want the app to work.

Open the full chapterIncludes a note
Thirty days later every request fails. You search the error, find a fix that makes it go away, and paste it in. The app works again.
That fix was a new expiry date, or allow read, write: if true;. Now your database has no lock at all. Anyone who finds your project ID can read your users, change them, or delete them.
02THE SPIRIT BOX
What “test mode” actually means
Why it mattersTest mode is a 30-day pass for everyone. Extending it extends the pass.
When you create a database or storage instance, Firebase asks you to choose. In its own words, you choose whether your rules “restrict access to your data (Locked mode) or allow anyone access (Test mode).”

Open the full chapterIncludes code
The Firestore quickstart says test mode is “good for getting started” but “allows anyone to read and overwrite your data.”
The test-mode rule, word for word
This is the template the Firebase CLI writes for you. The comment is Google’s, not ours:
rules_version='2'
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
// This rule allows anyone with your database reference to view, edit,
// and delete all data in your database. It is useful for getting
// started, but it is configured to expire after 30 days because it
// leaves your app open to attackers. At that time, all client
// requests to your database will be denied.
//
// Make sure to write security rules for your app before that time, or
// else all client requests to your database will be denied until you
// update your rules.
allow read, write: if request.time < timestamp.date(2026, 11, 15);
}
}
}The CLI fills in a real date 30 days out. Until that date, anyone can read, edit and delete everything.
The mistake is what happens on day 30
When the date passes, every request from your app is denied. That’s the safe part. The danger is the quick fix: push the date out a year, or swap the condition for if true. Both keep the door open, and the second one never closes.
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this ruleset in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}Firebase’s own warning, copied from its docs: never use this in production.
service cloud.firestore {
match /databases/{database}/documents {
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
}
}Firebase’s own owner-only sample: each user reads and changes only their own document.
03THE UNMASKING
Who is the ghost? Anyone.
Why it mattersThe stranger isn’t clever. The rule just says “anyone”.
Open rules don’t need a hacker. Firebase’s page on insecure rules says it plainly: “You might think you’re the only person using your app, but if you’ve deployed it, it’s available on the internet.”

Open the full chapterIncludes a table, a note
It goes on: if you’re not authenticating users and configuring security rules, “anyone who guesses your project ID can steal, modify, or delete the data.”
This happened to Tea
Tea, a dating-safety app for women, was breached in July 2025. Its own statement blamed a “legacy data storage system”. The leaked dataset held “approximately 72,000 images, including approximately 13,000 selfies and photo identification submitted by users during account verification”.
According to 404 Media, which broke the story, 4chan users said they had found an exposed database on Firebase. Days later, TechCrunch reported a second exposure: over 1.1 million private messages.
| What leaked | How many | Source |
|---|---|---|
| Selfies and photo IDs from account checks | About 13,000 | Tea’s statement |
| Images from posts, comments and DMs | About 59,000 | Tea’s statement |
| Private messages | Over 1.1 million | TechCrunch |
04RULES 1 + 2
Signed in first, then owner only
Why it mattersSigned in tells you who they are. Owner only decides what they can open.
The first rule is easy: only signed-in users get in. That alone stops strangers. But it doesn’t stop your other users.

Open the full chapterIncludes code
Why auth != null alone is not enough
Firebase warns about this exact rule. If a rule includes auth != null, it says to “confirm that you want any logged-in user to have access to the data”. Anyone can sign up for your app. Then they can read every record.
// Not recommended: any logged-in user can read and write everything
match /{document=**} {
allow read, write: if request.auth != null;
}Firebase’s verdict on this pattern: “Not recommended: Any logged-in user has read and write access to your entire database.”
The owner-only rule (Cloud Firestore)
Store each user’s data at users/{their uid}, then check the ID on every request. This is the sample from Firebase’s docs, exactly:
service cloud.firestore {
match /databases/{database}/documents {
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
}
}If your documents live in a shared collection instead, save the owner’s ID in each one and check that field:
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /some_collection/{document} {
// Allow reads and deletion if the current user owns the existing document
allow read, delete: if request.auth.uid == resource.data.author_uid;
// Allow creation if the current user owns the new document
allow create: if request.auth.uid == request.resource.data.author_uid;
// Allow updates by the owner, and prevent change of ownership
allow update: if request.auth.uid == request.resource.data.author_uid
&& request.auth.uid == resource.data.author_uid;
}
}
}The update rule checks both the old and new owner, so nobody can hand a document to themselves.
The same lock for Realtime Database
{
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this ruleset in production; it allows
// anyone to overwrite your entire database.
"rules": {
".read": true,
".write": true
}
}Open to everyone, forever.
{
"rules": {
"some_path": {
"$uid": {
// Allow only authenticated content owners access to their data
".read": "auth !== null && auth.uid === $uid",
".write": "auth !== null && auth.uid === $uid"
}
}
}
}Each signed-in user reads and writes only under their own ID.
05RULE 3
Lock the attic too: Cloud Storage rules
Why it mattersThree rules files, three locks. Missing one leaves a window open.
Profile pictures, uploads and ID photos usually live in Cloud Storage. It has its own storage.rules, separate from your database rules. An app can have a locked database and an open bucket.

Open the full chapterIncludes code, a note
// Anyone can read or write to the bucket, even non-users of your app.
// Because it is shared with App Engine, this will also make
// files uploaded using App Engine public.
// Warning: This rule makes every file in your Cloud Storage bucket accessible to any user.
// Apply caution before using it in production, since it means anyone
// can overwrite all your files.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}Firebase: “This rule makes every file in your Cloud Storage bucket accessible to any user.”
// Grants a user access to a node matching their user ID
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/file.txt"
match /user/{userId}/{fileName} {
allow read, write: if request.auth.uid == userId;
}
}
}Save each user’s files under user/<their uid>/. Only they can read or write them.
{
"firestore": { "rules": "firestore.rules" },
"database": { "rules": "database.rules.json" },
"storage": { "rules": "storage.rules" }
}firebase deploy --only firestore:rules,storage,databaseDeploys only your rules. Run it after the Playground test below passes.
06THE TEST
Prove it: the Rules Playground says “denied”
Why it mattersA rule you never tested is a guess. Denied is the answer you want.
Don’t trust a rule because it looks right. Test it the way the stranger would come in. Firebase’s docs: “To quickly test your updated Firebase Security Rules in the Firebase console, use the Rules Playground.”

Open the full chapterIncludes steps, a table, a note
- Open the Firebase console, go to Firestore Database → Rules (or Realtime Database or Storage), and open the Rules Playground.
- Pick get as the simulation type. For Location, enter someone else’s record, like
users/some-other-user-id. - Set Authentication type to unauthenticated. Click Run.
- The banner above the editor must say the request was denied. If it says allowed, your door is open.
- Now test as a signed-in user with a specific ID. Reading their own
users/<that id>should be allowed. Reading someone else’s should be denied.
| Who | Reads | Expected |
|---|---|---|
| Unauthenticated | Any user’s record | Denied |
| Signed in as user A | users/A | Allowed |
| Signed in as user A | users/B | Denied |
| Unauthenticated | A file in user/B/ | Denied |
07CASE CLOSED
Your before-launch rules check
Why it mattersFive minutes with the Playground beats a headline about your app.
Paste the prompt at the top of this page into Claude Code, Cursor or any coding agent. It finds your rules files, lists every open rule with its file and line, and suggests the owner-only version. It changes nothing until you say so.

Open the full chapterIncludes a table, a note
| Check | Bad sign | Good sign |
|---|---|---|
| Firestore rules | if true or request.time < timestamp.date(...) | request.auth.uid == userId |
| Realtime Database rules | ".read": true or ".write": true | auth.uid === $uid |
| Cloud Storage rules | allow read, write; on {allPaths=**} | Files under user/{userId}/ checked against request.auth.uid |
| Signed-in check | auth != null alone on personal data | Signed in AND owner only |
| Where rules live | Only in the console | In the repo, listed in firebase.json |
| Proof | It looks right | Rules Playground: unauthenticated read is denied |
THE QUICK READ
What to take away.
In one minute.
- 01
Firebase’s own docs say test mode “allows anyone to read and overwrite your data.”
- 02
The test-mode rule expires after 30 days. The mistake is what comes next: a new date, or
if true, so the app works again. - 03
Your project ID ships inside your app. Firebase says “anyone who guesses your project ID can steal, modify, or delete the data.”
- 04
Signed in is not enough. With
request.auth != nullalone, every user can read every other user’s records. - 05
Owner-only rules check the user’s ID:
request.auth.uid == userId. Cloud Storage needs its own rules too. - 06
Test it in the Rules Playground as an unauthenticated user. A read of someone else’s record must say denied.
THE FIX, IN ONE PASTE
Paste this. Find every open door in your rules.
Paste this into Claude Code, Cursor, Codex, Gemini CLI or Copilot. It only reads and reports; it won’t change your code until you approve.
You are a security reviewer for this codebase. Investigate ONE issue: Firebase Security Rules that let anyone, or any signed-in user, read or change other people's data.
Where to look:
- `firebase.json` (it names the rules files), then `firestore.rules`, `database.rules.json`, `storage.rules` and any other `*.rules` file.
- Every collection, path and Storage folder the app really uses: `collection(`, `doc(`, `ref(`, `uploadBytes(`.
How to judge each rule:
- Critical: `if true`, `allow read, write;` with no condition, `".read": true` or `".write": true`.
- Critical: test-mode rules, `request.time < timestamp.date(...)`, even if the date is in the future. Say when it expires.
- High: `request.auth != null` (or `auth != null`) alone on personal data. Any signed-in user can read every record.
- OK: owner-only rules, like `request.auth.uid == userId` on `/users/{userId}`, `auth.uid === $uid`, or `request.auth.uid == resource.data.author_uid`.
- Also flag Storage paths that are not scoped to the user's ID, and say if no rules files are in the repo (then the live rules exist only in the Firebase console).
Report a table: file:line | what's wrong | severity (critical, high, medium, low) | the minimal owner-only rule.
Then explain how to check each fix in the Firebase console's Rules Playground: Authentication type unauthenticated, a path to someone else's record, Run, expect denied.
Rules: don't modify any file or deploy rules until I approve. Never print keys, config values or user data: mask them.
Then ask me which fixes to apply.Paste it into the agent you already build with
- Claude
- ChatGPT
- Gemini
- Cursor
- Copilot
QUESTIONS PEOPLE ASK
Good questions.
Short answers.
What is Firebase test mode?
It’s a starting rule set you can pick when you create a database or bucket. Firebase’s quickstart says it is good for getting started but “allows anyone to read and overwrite your data.” The Firebase CLI version expires after 30 days.
What happens when Firebase test mode expires?
All client requests to your database are denied until you update your rules. Don’t fix it by pushing the date out or switching to if true. Write owner-only rules instead.
Is allow read, write: if true ever OK?
Not in production. Firebase’s own sample carries the warning “NEVER use this ruleset in production; it allows anyone to overwrite your entire database.”
Is request.auth != null enough?
No, not for personal data. It only checks that someone is signed in. Anyone can create an account, so every user could read every other user’s records. Add an owner check like request.auth.uid == userId.
Isn’t my Firebase config a secret?
No. The config and project ID ship inside your app, so treat them as public. Your security rules are what protect the data.
How do I test my Firebase rules?
Use the Rules Playground in the Firebase console: set Authentication type to unauthenticated, enter someone else’s record as the location, and click Run. It must be denied. For automated tests, use the Firebase Emulators.
Do I need separate rules for Cloud Storage?
Yes. Cloud Storage has its own storage.rules. Locking Firestore or Realtime Database doesn’t protect uploaded photos and files.
Does Aster check my Firebase rules?
Aster reads your repository. Its scan flags Firestore, Realtime Database and Storage rules files that are open, in test mode, or open to any signed-in user. It can’t see rules you only published in the Firebase console, and it doesn’t prove one user can’t read another’s data. The Rules Playground test above covers that.
Delete “allow everyone”, check the owner on every record and file, and test as a stranger until it says denied. Then get a second look: your first Aster repository audit is free, and it flags open Firebase rules, keys left in code and vulnerable packages.
Source notebook11 links
- Firebase Docs: Avoid insecure rules (open rules, any signed-in user, content owner only)
- Firebase Docs: Basic Security Rules (Locked mode and Test mode)
- Firebase CLI (firebase-tools): the test-mode firestore.rules template
- Firebase Docs: Cloud Firestore quickstart (Test mode vs Locked mode)
- Firebase Docs: Writing conditions for Cloud Firestore Security Rules (the userId pattern)
- Tea Dating Advice: official cyber incident statement (archived 2025-07-30)
- 404 Media (2025-07-25): Women Dating Safety App ‘Tea’ Breached, Users’ IDs Posted to 4chan
- TechCrunch (2025-07-29): Tea app’s data breach gets much worse
- Firebase Docs: Quickly validate Firebase Security Rules (Rules Playground)
- Firebase Docs: Set up the Emulator Suite to test Security Rules
- Firebase Docs: Fix insecure rules in Cloud Firestore (the alert email)

