Guides / Firebase security rules still in test mode? How to check and lock them down

last checked oct 2026

Firebase security rules still in test mode? How to check and lock them down

When you create a Firestore database, Firebase asks you to pick a starting mode. Test mode is the easy one, and Firebase's own docs say it “allows anyone to read and overwrite your data.” A lot of apps launch without ever leaving it.

The short answer

If your Firestore rules contain match /{document=**} with allow read, write: if true; or if request.time < timestamp.date(…), then anyone who knows your project ID can read, change and delete your whole database until that date. Pushing the date forward doesn't fix it. Delete the catch-all rule and write a rule for each collection that checks request.auth.uid against the document's owner.

Your Firebase web config (apiKey, projectId and so on) being visible in the frontend is normal. Firebase says those API keys only identify your project, and access is controlled by Security Rules, IAM and App Check. Your rules are what actually protect the data.

What “test mode” looks like

A database created in test mode typically starts with a rule like this, with a date about 30 days out:

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

When that date passes, every client request is denied and the app breaks. The tempting quick fixes are to bump the date or change the condition to if true, and both leave the database open. You'll often see these patterns too, all of which Firebase lists as insecure:

// Open to everyone
allow read, write: if true;

// Any signed-in user can read and write every document
allow read, write: if request.auth != null;
// Realtime Database equivalent of "open to everyone"
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
// Cloud Storage: every file readable and writable by anyone
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write;
    }
  }
}

How to check

1. Read the rules that are actually deployed

In the Firebase console, open Firestore → Rules, and do the same for Realtime Database → Rules and Storage → Rules if you use them. The console always shows the most recently deployed version. If you deploy from the CLI, the local files are listed in firebase.json (usually firestore.rules, database.rules.json, storage.rules), but they can drift from what's live, so trust the console.

Red flags:

Firestore rules can only grant access. If any matching allow is true, the request goes through. That means one broad catch-all overrides every careful rule below it. Realtime Database rules cascade the same way: once a parent path grants read, a child rule can't take it back.

2. Test it from outside, without signing in

Against your own project, request a collection through the Firestore REST API with no auth token. Firebase evaluates unauthenticated REST requests against your Security Rules, just like the SDK:

curl "https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/users?pageSize=1"

Documents in the response mean the collection is publicly readable. A PERMISSION_DENIED error is what you want. For Realtime Database, use the database URL shown at the top of its console page. The shallow=true parameter returns only the top-level keys, so you don't download everything:

curl "https://YOUR_DATABASE_URL/.json?shallow=true"

3. Use the Rules Playground

In Firestore → Rules, open the Rules Playground to simulate reads and writes as an unauthenticated user and as a specific user ID. It runs against the rules in your editor, so you can try a fix before you publish it.

How to fix it

Write rules per collection, tied to the owner

Start from deny, then open exactly what each collection needs. Here's an owner-only pattern for user documents, plus a “public read, owner write” pattern, adapted from Firebase's examples:

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

    // Each user can only touch their own profile
    match /users/{userId} {
      allow read, write: if request.auth != null
                         && request.auth.uid == userId;
    }

    // Anyone can read posts; only the author can create, edit or delete
    match /posts/{postId} {
      allow read: if true;
      allow create: if request.auth != null
                    && request.auth.uid == request.resource.data.author_uid;
      allow update: if request.auth != null
                    && request.auth.uid == resource.data.author_uid
                    && request.auth.uid == request.resource.data.author_uid;
      allow delete: if request.auth != null
                    && request.auth.uid == resource.data.author_uid;
    }
  }
}

The update rule checks both the existing document (resource) and the new one (request.resource), so nobody can take over a post by rewriting author_uid. Remove the old /{document=**} block completely. Leaving it in place cancels everything above.

If the database is only used from your server (Admin SDK or Cloud Functions), you can lock clients out entirely with allow read, write: if false;. Server client libraries and the Admin SDK aren't subject to Security Rules, and they authenticate through IAM instead.

Do the same for Realtime Database and Storage

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    match /user/{userId}/{fileName} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

Deploy and verify

firebase deploy --only firestore:rules
firebase deploy --only database,storage

Firestore rule changes can take up to a minute to affect new queries, and up to 10 minutes to reach active listeners. Then re-run the curl checks above. Deploying from the CLI overwrites rules edited in the console, so pick one place to edit and stick to it. To keep this from regressing, Firebase recommends testing rules with the Local Emulator Suite before each deploy.

next step

Check your live app for free

Our free Leak Checker looks at your deployed app the way any visitor's browser does and flags exposed secret keys, public source maps and missing security headers. It can't see your Firebase rules, but it checks the JavaScript you ship for secret keys that should never be there, like a service account or third-party API secret.

If you'd rather have the whole app looked at, the $99 Scan + Report covers your repo and live app, including Supabase RLS, leaked keys and auth checks.

Sources

Every product step above was checked against these official pages. Last checked Oct 2026. Products change; if a menu moved, the docs below are the source of truth.