Firebase Security Rules: We Tested Open vs Locked Rules

Firebase security rules decide who can read and write your Firestore, Realtime Database and Storage data. Your public API key doesn't protect data. The rules do, so lock them before launch.

Gary 路 Published 路 Updated 路 17 min read 路 Tested on our demo app on

Isometric illustration of a glowing gate standing between a browser window and three data stores, with emerald light on a dark slate background.
On this page
  1. What are Firebase security rules?
  2. Is Firebase secure if my API key is public?
  3. What does Firebase "test mode" actually allow? We tested it.
  4. Firestore rules: from wide open to owner-only
  5. Why "rules aren't filters" trips people up
  6. Firebase Realtime Database rules (a different syntax)
  7. Firebase Storage rules for uploads
  8. How do I test Firebase security rules before launch?
  9. What does Firebase App Check add (and what doesn't it)?
  10. Firebase rules pre-launch checklist
  11. What our scanner shows for a Firebase app
  12. FAQ
  13. Check your app before launch

Firebase security rules decide who can read and write the data in your Firestore database, Realtime Database and Cloud Storage bucket. Your app's Firebase config, API key included, is public by design. The rules are what stand between that public config and your users' data. We tested open rules and locked rules side by side on Firebase's local emulator, and this guide shows what got through.

By Gary, Greenlight My App 路 Updated Oct 28, 2026 路 How we checked this: on Oct 28, 2026 (about 7:00 to 7:05 AM ET) we ran the Firebase Local Emulator Suite on our own machine with a demo project (demo-greenlight) and fake data only. We swapped in each rule set and sent plain REST requests with and without a fake signed-in user, then ran rules unit tests. No Google account, no real Firebase project and no rules deployed anywhere. Firebase's public docs were read the same morning. Drafted with AI tools and reviewed by a person before publishing.

What are Firebase security rules?

Firebase security rules are the rules that decide whether each read or write is allowed when a browser or app talks straight to Firestore, the Realtime Database or Cloud Storage. When there's no server of yours in between, the rules are your access control.

In a typical app built with an AI tool, the frontend calls Firebase directly. There is no backend of yours checking requests first. So every request is judged by the rules alone: who is signed in (request.auth), what they are asking for, and what the data looks like.

Each product has its own rules file. Firestore and Cloud Storage use a rules language with match and allow statements. The Realtime Database uses JSON with .read and .write keys. All three are covered below, with results from our emulator run.

Diagram: the browser holds a public web config and a fake API key, passes an optional App Check step, then reaches a Security Rules gate. Test mode or if true leaves the gate open; locked, owner-only and validation rules check request.auth and the data before Cloud Firestore, Realtime Database or Cloud Storage The public key gets a request to the door. Security Rules decide who gets in. Original diagram by Greenlight My App, based on Firebase's docs (Oct 28, 2026).

Is Firebase secure if my API key is public?

It can be, if your rules are right. Firebase's docs say API keys for Firebase services only identify your project and app, and that authorization comes from IAM permissions, Security Rules and App Check. Keys restricted to Firebase APIs don't need to be treated as secrets. Open rules, not the visible key, are the risk.

So a firebase api key showing up in your page source is expected. Firebase's API keys page (external), checked Oct 28, 2026, adds two cautions: apply API restrictions to every key, and use a separate, restricted key for other Google APIs. It says a key for the Gemini Developer API must never be in your code. If you want the general idea of public versus secret keys, see what an API key is (external). For how Firebase's public key compares with Supabase's, see our Supabase vs Firebase comparison (external).

Firebase's API keys docs page with two highlighted points: API keys for Firebase services only identify your project, and data security is enforced by Security Rules and App Check, not by keeping the key secret Firebase's API keys docs. Highlight added by Greenlight My App. Screenshot of firebase.google.com/docs/projects/api-keys, Oct 28, 2026.

What does Firebase "test mode" actually allow? We tested it.

Firebase's docs say test mode grants access to all users. In our emulator test, a test-mode rule and an if true rule both let a request with no sign-in list every document and write a new one. Locked rules (if false) denied the same requests, even for a signed-in user.

When you create a database or bucket in the Firebase console, the docs say you choose Locked mode (deny everyone) or Test mode (allow everyone). The insecure-rules page (external) warns that if your rules are open, anyone who guesses your project ID can steal, change or delete your data.

Firebase's Avoid insecure rules docs page with the paragraph highlighted that says you can choose Locked mode to deny all users or Test mode to grant access to all users Firebase's docs on Locked mode vs Test mode. Highlight added by Greenlight My App. Screenshot of firebase.google.com/docs/rules/insecure-rules, Oct 28, 2026.

Here is the test-mode rule we used (yours will show its own date). It allows everything until a set date, and we used a date 30 days out:

Text

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

Results from the emulator, with fake data only:

Rule setRequestSigned in?Result
Test mode (open until a date)List all notesNoAllowed (all 3 fake docs returned)
Test modeCreate a docNoAllowed
allow read, write: if trueList all notesNoAllowed
allow read, write: if trueCreate a docNoAllowed
Locked (if false)List all notesNoDenied (403)
Locked (if false)Create a docNoDenied (403)
Locked (if false)List all notesYesDenied (403)

Source: our emulator run, Oct 28, 2026 (Firebase Local Emulator Suite, project demo-greenlight).

Firebase Emulator UI Requests tab showing a LIST request on the notes collection allowed with a green check, and the test-mode rule line highlighted Test mode: the emulator allowed an unauthenticated list of every note. Box added by Greenlight My App. Emulator UI, Oct 28, 2026.

Firebase Emulator UI Requests tab showing the same LIST request denied with a red icon, and the if false rule line highlighted Locked rules: the same request, denied. Box added by Greenlight My App. Emulator UI, Oct 28, 2026.

The time limit is a deadline, not protection. Until that date passes, anyone can read and write. When it passes, everything is denied, including your own app, and people often "fix" that by pushing the date out or switching to if true. Neither makes the data safe.

Firestore rules: from wide open to owner-only

Good Firestore rules start locked and open only what each user needs. A common pattern is owner-only: a user can read and change a document only if its owner field matches their user ID. In our test, that let a user read their own note and blocked everyone else.

Here are the four steps we tested, in order. Each is a complete set of firestore security rules you can compare with your own.

1. Wide open (never ship this). Firebase's docs mark this ruleset "NEVER use this ruleset in production".

Text

match /{document=**} {
  allow read, write: if true;
}

2. Locked. Nothing from the browser gets in. Fine before you write real rules.

Text

match /{document=**} {
  allow read, write: if false;
}

3. Owner-only. Each note has an owner field holding the user's ID.

Text

match /notes/{noteId} {
  allow read, update, delete: if request.auth != null
    && request.auth.uid == resource.data.owner;
  allow create: if request.auth != null
    && request.auth.uid == request.resource.data.owner;
}

4. Owner-only plus data validation. This rule only accepts the fields you expect, with the right types. Firebase's docs describe checking incoming data through request.resource.data.

Text

match /notes/{noteId} {
  allow create: if request.auth != null
    && request.resource.data.keys().hasOnly(['owner', 'title', 'body'])
    && request.resource.data.keys().hasAll(['owner', 'title'])
    && request.resource.data.owner == request.auth.uid
    && request.resource.data.title is string
    && request.resource.data.title.size() > 0
    && request.resource.data.title.size() <= 100;
}

(Our tested version also allowed an optional body field if it was a string.)

Results table rendered from the emulator log: owner-only rules allowed alice to read her own note and a query filtered to her notes, and denied a read with no user, a read of another user's note, a read as a different user and a list of the whole collection. Validation allowed a good write and denied a write with a number title and an extra isAdmin field Owner-only and validation results. Rendered by Greenlight My App from the emulator request log, fake users and data, Oct 28, 2026.

Why "rules aren't filters" trips people up

With owner-only rules, our signed-in test user asked for the whole notes collection. She owns one of the three notes, but the whole request was denied. Firebase's docs (external) explain why: rules are not filters, and queries are all or nothing. If a query could return any document the user can't read, the entire request fails. When the same user ran a query limited to owner == her ID, it was allowed and returned only her note.

So the fix is in your app's query, not in loosening the rules. Ask for what the user is allowed to see.

Firebase's Securely query data docs page with the Rules are not filters paragraph highlighted, saying that if a query could return documents the client can't read, the entire request fails Firebase's docs on rules and queries. Highlight added by Greenlight My App. Screenshot of firebase.google.com/docs/firestore/security/rules-query, Oct 28, 2026.

The bad write in our validation test tried to save a number as the title and sneak in an extra isAdmin: true field. It was denied. Without validation, a user could write any fields they like into their own documents, including ones your app might later trust.

Firebase Realtime Database rules (a different syntax)

Firebase Realtime Database rules are written in JSON, with .read and .write keys on paths in your data tree. Open rules let anyone read the whole database in one request. In our test, auth != null still let any signed-in user read everything, so per-user paths were the version that actually separated users.

Three versions of these firebase database rules, from open to per-user:

JSON

{ "rules": { ".read": true, ".write": true } }
JSON

{ "rules": { ".read": "auth != null", ".write": "auth != null" } }
JSON

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}

We sent a plain read of the database root (/.json) under each one:

RulesRequestSigned in?Result
.read: trueRead the whole treeNoAllowed
auth != nullRead the whole treeNoDenied (401)
auth != nullRead the whole treeYesAllowed (every user's records)
Per-user $uidRead the whole treeNoDenied (401)
Per-user $uidRead the whole treeYesDenied (401)
Per-user $uidRead /users/<own ID>YesAllowed
Per-user $uidRead another user's pathYesDenied (401)

Source: our emulator run, Oct 28, 2026.

Results table rendered from the emulator log for Realtime Database root reads: open rules allowed an unauthenticated read, auth not null allowed any signed-in user to read every record, and per-user rules allowed only the user's own path Realtime Database results. Rendered by Greenlight My App from the emulator request log, fake data, Oct 28, 2026.

The middle row is the one to watch. Firebase's insecure-rules page flags it too: if a rule uses auth != null, confirm that you want any logged-in user to have access to the data. If your app lets anyone sign up, that is close to open.

Firebase Storage rules for uploads

Firebase Storage rules control who can download and upload files in your bucket. With if true, our request with no sign-in downloaded a user's file and uploaded a new one. With rules that allow each signed-in user only their own folder, both were denied, and the user could still use their own folder.

The two versions of firebase storage rules we tested:

Text

// Open (don't ship)
match /b/{bucket}/o {
  match /{allPaths=**} {
    allow read, write: if true;
  }
}

// Own folder only
match /b/{bucket}/o {
  match /users/{userId}/{fileName} {
    allow read, write: if request.auth != null && request.auth.uid == userId;
  }
}
RulesRequestSigned in?Result
if trueDownload a user's fileNoAllowed
if trueUpload a fileNoAllowed
Own folder onlyDownload a user's fileNoDenied (403)
Own folder onlyUpload a fileNoDenied (403)
Own folder onlyDownload own fileYesAllowed
Own folder onlyUpload to own folderYesAllowed
Own folder onlyUpload to another user's folderYesDenied (403)

Source: our emulator run, Oct 28, 2026.

Results table rendered from the emulator log for Cloud Storage: open rules allowed an unauthenticated download and upload; own-folder rules denied both and allowed the signed-in user to use only her own folder Cloud Storage results. Rendered by Greenlight My App from the emulator request log, fake files, Oct 28, 2026.

Open upload rules are a separate problem from open reads: anyone could put files in your bucket. We didn't measure cost or abuse in this test; we only checked whether each request was allowed.

How do I test Firebase security rules before launch?

Run them on the Firebase Local Emulator Suite and write unit tests that expect both successes and failures. Firebase's docs recommend the emulators for developing rules and show unit tests with its rules-unit-testing library. Our six tests all passed in about 1.5 seconds.

What we did, which you can copy with your own rules:

  1. Start the emulators with a demo project ID (we used demo-greenlight), so nothing touches a real Firebase project.
  2. Seed a few fake records, including one owned by a fake test user.
  3. Write tests with @firebase/rules-unit-testing, as in Firebase's unit test docs (external): assertSucceeds for what should work (a user reading their own note) and assertFails for what shouldn't (no user, another user's note, a bad write).
  4. Watch the Emulator UI's Requests tab. It shows each request and which rule line allowed or denied it, like the screenshots above.

Terminal output of node --test rules.test.mjs showing six passing tests: Firestore locked, Firestore open, owner-only rules aren't filters, data validation, Realtime Database open vs auth vs per-user, and Storage open vs own folder Our rules unit tests: 6 tests, 6 passed, 0 failed. The PERMISSION_DENIED line is the expected denial of the bad write. Oct 28, 2026.

Firebase's docs also describe a rules simulator (the Rules Playground in the Firebase console) for simulating signed-in and signed-out requests. It works on a real project, so we used the Emulator UI instead and don't show it here. Firebase's docs recommend more thorough testing with the emulator before you deploy.

If an AI tool wrote your rules, run these tests before you trust them. A rule can look strict and still let more through than you expect, like auth != null in the Realtime Database test above. A failing assertFails test shows you that before your users do.

What does Firebase App Check add (and what doesn't it)?

Firebase App Check helps confirm that requests come from your real app on a real device, using attestation providers. Firebase's docs say it prevents some, but not all, abuse and doesn't guarantee to stop it all. It doesn't decide which user can read which data. That is still your security rules' job.

Firebase's API keys page puts it this way: Security Rules control which end users can access resources, and firebase app check controls which apps can. So they answer different questions. App Check asks "is this my app?" Rules ask "is this user allowed to read this document?" A request from your real app, made by a signed-in user, still needs rules that stop that user reading other people's data.

Firebase's App Check docs page with the paragraph highlighted that says App Check prevents some, but not all, abuse vectors and does not guarantee the elimination of all abuse Firebase's App Check docs (external). Highlight added by Greenlight My App. Screenshot of firebase.google.com/docs/app-check, Oct 28, 2026.

Firebase rules pre-launch checklist

Before you launch, make sure your firebase rules have no test-mode or if true lines, user data is owner-only, writes are validated, Storage is per user, and every rule set has passing emulator tests. Then restrict your API key and consider App Check.

CheckWhat "done" looks likeWhere it's covered
Test mode is goneNo request.time < open-until-a-date rule leftTest mode section
No if true rulesSearch all three rules files for if true and ".read": trueFirestore, Realtime Database and Storage sections
Owner checks on user datarequest.auth.uid compared with the owner field or pathOwner-only rules
auth != null isn't your only checkSigned-in users can't read each other's dataRealtime Database section
Writes are validatedOnly expected fields and types are acceptedValidation rule
Storage is locked per userUploads and downloads limited to the user's own folderStorage section
Rules tested on the emulatorUnit tests with both assertSucceeds and assertFails passTesting section
API key restrictedAPI restrictions applied; separate keys for non-Firebase APIsAPI key section
App Check consideredTurned on where it fits, never instead of rulesApp Check section
Server keys never in the browserService account keys and other secrets stay in server environment variablesWhat is a .env file? (external)

If you also use Supabase, the same idea there is row level security. Our guides to Supabase RLS (external) and Postgres row level security (external) cover it. For a full pre-launch pass, use the Lovable launch checklist (external) or the Bolt.new launch checklist (external).

What our scanner shows for a Firebase app

We also ran the Greenlight My App scanner against a local demo page holding an obviously fake Firebase web config. The only related finding was an INFO note: "Google API key found in your code (usually OK)". That matches Firebase's docs on public keys. The scan does not check your Firebase security rules. It made no request to Firestore, the Realtime Database or Storage, so it can't tell you whether your rules are open. Use the emulator tests above for that.

Scan result rendered from the scan output for a demo page with a fake Firebase web config: one INFO row under Exposed secrets reading Google API key found in your code (usually OK) The scan's only Firebase-related finding on our demo page. Rendered from the scan output file, Oct 28, 2026. Fake config, local page.

FAQ

Is it safe that my Firebase API key is public? Yes, for a key restricted to Firebase services. Firebase's docs say these keys only identify your project and app, and that access is controlled by Security Rules, IAM and App Check, not by hiding the key. Apply API restrictions, keep other Google API keys separate, and make sure your rules aren't open.

What can hackers do with my Firebase API key? On its own, a Firebase web API key identifies your project; it doesn't grant access to data. What someone can do depends on your security rules. If your rules are in test mode or use if true, anyone with your project details can read and write your data, as our emulator test showed. Locked, owner-only rules stop that.

How do I find the API key for a Firebase app? For a web app, Firebase's docs say it's the apiKey field in your Firebase config object. For Apple apps it's in GoogleService-Info.plist, and for Android in google-services.json. You can see and manage all your project's keys on the Credentials page of the Google Cloud console, where you also apply restrictions.

What does Firebase test mode allow? Firebase's docs say test mode grants access to all users. In our emulator test, a test-mode rule let a request with no sign-in list every Firestore document and create a new one. A time-limited test rule only stops working on its end date, so treat it as open until you replace it.

How do I lock down Firestore rules? Start from allow read, write: if false, then open only what each user needs. Compare request.auth.uid with an owner field so users reach only their own documents, and validate the fields and types on every write. Query only for documents the user may read, because rules aren't filters. Then test it all on the emulator.

Are Firebase rules the same for Firestore, Realtime Database and Storage? No. Each product has its own rules. Firestore and Cloud Storage use the same rules language with match and allow statements, but separate files and paths. The Realtime Database uses JSON with .read and .write keys. You need to lock down each product your app uses; securing one doesn't secure the others.

How do I test Firebase security rules? Use the Firebase Local Emulator Suite with a demo project and fake data, and write unit tests with the @firebase/rules-unit-testing library. Include tests that should fail, such as reading another user's data. The Emulator UI's Requests tab shows which rule line allowed or denied each request. The console's Rules Playground works on a real project.

Does App Check replace security rules? No. Firebase's docs say App Check uses attestation to help confirm requests come from your authentic app and prevents some, but not all, abuse. It doesn't decide which user can read which data. Security Rules do that. Use App Check alongside locked, owner-only rules, never instead of them.

Check your app before launch

Built your app on Firebase with Lovable, Bolt, Cursor, Replit or v0? Scan your app before launch with Greenlight My App's free scan. It looks for keys and settings that shouldn't be there in your homepage and up to 15 of the scripts it loads. It doesn't test your Firebase security rules, so run the emulator checks above too. The scan is automated, read-only and educational, not a security audit, and "nothing found" isn't a guarantee that nothing is exposed.

Sources

On this site

Related posts

Greenlight My App is independent and not affiliated with or endorsed by Google, Firebase, Lovable, StackBlitz (Bolt), Anysphere (Cursor), Replit or Vercel (v0). Firebase and Google are trademarks of Google LLC. All product names are trademarks of their owners. Firebase facts are paraphrased from Firebase's public docs as checked on Oct 28, 2026, and can change. This page is general information, not professional security advice, legal advice, a security audit or a guarantee. Check your own setup against the vendor's current docs.