Join our Newsletter — 33% off our NHI Course
Home› Guides› Firebase Security Rules Guide: Writing, Testing and Monitoring…
Guide Cloud Security

Firebase Security Rules Guide: Writing, Testing and Monitoring Rules for Firestore, Realtime Database and Storage

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 27 October 2026 13 min read
On this page

In a Firebase app the client talks straight to the database, so Security Rules are the only thing standing between a public API key and every record you hold. Open or weak rules are behind some of the largest mobile and web data exposures on record, including 916 websites that leaked more than 125 million user records. This guide explains how rules authorise requests in Cloud Firestore, Realtime Database and Cloud Storage for Firebase, the insecure patterns Firebase itself warns about, safe patterns for ownership and roles, why rules are not filters, how to test rules in CI with the Emulator Suite, and how App Check and IAM fit around them. It complements our Firebase Credentials Security Guide, which covers keys and service accounts, and is written for mobile and web developers, application security engineers and reviewers.

Key takeaways

  • The API key is not the control. Firebase states that API keys for Firebase services only identify your project and app; authorisation comes from Security Rules, IAM and App Check.
  • Signed in is not authorised. Rules that only check request.auth != null let every account holder, including someone who just registered, read and write the data.
  • Rules are not filters. A Firestore query must itself be constrained so every possible result passes the rule, otherwise the whole query fails; design data and queries together.
  • Realtime Database rules cascade. Access granted at a parent path cannot be revoked by a child rule, so a single broad grant near the root overrides everything below it.
  • Test rules like code. Use deny-by-default, unit test with @firebase/rules-unit-testing against the Emulator Suite in CI, and remember that server SDKs using a service account bypass rules entirely.

How identity and access work in Firebase Security Rules

Each client request to Firestore, Realtime Database or Cloud Storage for Firebase is evaluated against the deployed rules for that product. Firestore and Storage use a CEL-based language with service, match and allow statements; Realtime Database uses JSON with .read, .write and .validate keys. Firestore and Storage rules should start with rules_version = '2';, otherwise the v1 engine applies.

ElementFirestore and StorageRealtime Database
Who is callingrequest.auth (null if not signed in), request.auth.uid, request.auth.token claimsauth, auth.uid, auth.token
Existing dataresource.datadata
Incoming datarequest.resource.datanewData
Methodsget, list, create, update, delete (read and write as shortcuts).read, .write, .validate
Combining rulesA request is allowed if any matching complete rule allows it; broader grants override narrower onesRules cascade down: a child rule can add access but cannot remove access granted above
Lookupsget() and exists() on other documents, charged as readsReads of other paths through root and data

Matching. Only complete path matches are evaluated. {name} matches one segment and {name=**} matches any depth; Firebase advises against recursive wildcards unless the permissive rule should truly apply to every nested path. Because any allowing rule wins, one careless recursive match grants access that no narrower rule can take back.

Who bypasses rules. Rules apply to client SDK and REST requests made with end-user credentials. The Firebase Admin SDK and Google Cloud server client libraries authenticate with service account credentials and IAM, and are not subject to Security Rules. That makes service account keys and Cloud Functions identities the real administrators of your data. See the Firebase Credentials Security Guide.

Admin roles and privileged access

Who can change the rules matters as much as what the rules say: a single deploy can open the database.

  • Rules deployment: deploy rules from version control through the Firebase CLI in a pipeline, not by editing in the console. Restrict IAM roles that can update rulesets in production projects to the pipeline identity and a small break-glass group. Firebase's security checklist recommends limiting team access to production data with predefined or custom IAM roles, and notes that teams developing against the Emulator Suite may not need broad production access.
  • Test mode: Firebase warns that test mode grants access to all users when you create a database or bucket. Treat a project still on test-mode rules as an incident, not a backlog item.
  • Separate projects: keep development, staging and production in separate Firebase projects so permissive development rules and broad developer roles never touch production data.
  • Privileged users in the app: application administrators should be expressed through custom claims set by a trusted backend (request.auth.token.admin == true) or through role documents that clients cannot write, never through a field the user can edit on their own profile.

Insecure patterns and safe replacements

Firebase documents the following insecure patterns. Each maps to a safer replacement.

PatternWhy it is insecureSafer replacement
Open access: allow read, write: if true (Firestore); ".read": true, ".write": true at the root (Realtime Database); allow read, write with no condition (Storage)Firebase warns that anyone who guesses your project ID can steal, modify or delete dataDeny by default; open specific paths to specific users
Any authenticated user: request.auth != null aloneEvery signed-in user, including self-registered or anonymous accounts, gets full accessNarrow with conditions on uid, claims or document fields; require verified email or a non-anonymous provider for non-public data
Owner field without update checkA user can change the owner field and take over or give away documentsOn update, require the uid to match both resource.data and request.resource.data owner fields
Role stored in a user-writable documentUsers promote themselvesRole documents or custom claims written only by a trusted backend
Broad grant at a Realtime Database parentCascade means child rules cannot restrict itGrant at the narrowest path, for example /users/$uid
Writes without validationClients store arbitrary fields, sizes or types, including fields that later drive authorisationValidate request.resource.data keys, types and sizes on create and update; .validate in Realtime Database

Safe patterns

  • Content owner only: in Firestore, allow read and delete when request.auth.uid equals the document's owner field, check the owner field on create, and require it to match in both old and new data on update. In Realtime Database, scope to $uid with auth !== null && auth.uid === $uid. In Storage, match a per-user path such as user/{userId}/{fileName}.
  • Mixed public and private: public reads with writes restricted to the author.
  • Role-based: look up the caller's role document with get() and allow by role. Each lookup costs a read, so put cheap checks first in && and || expressions to short-circuit.
  • Attribute-based and group-based: compare token claims with document fields or, for Storage, with file metadata.

Language limits shape design: functions allow a single return statement with no loops or external calls, the call stack depth limit is 20, v2 allows up to 10 let bindings, and the compiled ruleset must stay under 250 KB. Keep helpers inside the match block that uses them.

Integrations, API tokens and service accounts

Queries and the rules-are-not-filters principle

Firestore evaluates a query against its potential result set, not the documents it actually returns. If a rule requires resource.data.published == true, the query must include where("published", "==", true); otherwise it fails even if every stored document happens to be published. For in, or and array-contains-any queries, every comparison value must satisfy the rule. A single document fetched by ID is evaluated on its actual contents. Rules can also inspect request.query (limit, offset and orderBy), which lets you deny list requests that do not set a limit, an effective brake on bulk scraping by a signed-in attacker.

App Check

App Check attaches a short-lived token proving the request came from your genuine app, using Play Integrity on Android, DeviceCheck or App Attest on Apple platforms and reCAPTCHA Enterprise on the web. It supports Cloud Firestore, Realtime Database, Cloud Storage for Firebase, callable Cloud Functions and other services. Firebase says it "prevents some, but not all, abuse vectors". It raises the cost of scripted access with your API key but does nothing against a user of your real app who is over-authorised by your rules. Use it as a layer on top of correct rules, never as a replacement.

Backend identities

  • Cloud Functions: the Admin SDK gets credentials automatically in Cloud Functions; do not add service account keys, and do not store secrets in environment variables, as the checklist advises. Every function that writes with the Admin SDK must do its own authorisation of the calling user.
  • Custom claims: claims are set by a backend with the Admin SDK and read in rules from request.auth.token. Restrict who can call the claim-setting code, because it is the path to admin rights in your rules.
  • Third-party integrations: exports, analytics and extensions run with service accounts. Inventory them and scope their IAM roles; rules will not stop them.

See the Google Cloud IAM and Service Accounts Guide and the Mobile App Security Guide.

Testing rules

Firebase recommends denying all access by default, writing rules alongside the data model and unit testing them with the Local Emulator Suite in CI.

Tool or functionPurpose
@firebase/rules-unit-testing (v9 API)The only library that supports mocking auth in Security Rules tests
initializeTestEnvironment({ projectId, firestore: { rules } })Creates the test environment against running emulators
authenticatedContext(uid, tokenOptions)Simulates a signed-in user, including custom claims
unauthenticatedContext()Simulates an anonymous client
assertSucceeds and assertFailsAsserts that an operation is allowed or denied
withSecurityRulesDisabledSeeds test data without rule evaluation
cleanup() and clearFirestore()Resets state between tests, since emulator data persists within a run

Two cautions from the documentation: if no rules file is configured and you do not load rules explicitly, the emulator applies open rules, so a passing test suite can be meaningless; and the emulators must be running or tests time out. Write negative tests first: an unauthenticated read of every collection, a signed-in user reading another user's document, a user changing their own role or owner field, and an unbounded list query. A failing negative test should block the deploy.

Logging and detection

  • Rules changes: ruleset releases are administrative changes to the Firebase Rules API and appear in Cloud Audit Logs for the project. Alert on any release not made by the pipeline identity.
  • Usage and denials: the Firebase console shows rules evaluation usage for each product. A sudden jump in allowed reads on a sensitive collection, or in denials, signals scraping or a broken release.
  • Traffic monitoring: the security checklist advises monitoring and alerting for Firestore, Realtime Database, Cloud Storage and Hosting to detect abusive traffic, and setting budget alerts, because a bulk read shows up first as cost.
  • App Check metrics: watch the share of unverified requests before and after enforcement.
  • External scanning: researchers found the exposure of 916 websites by scanning millions of domains for public Firebase configuration and testing access. Run the same check against your own projects: an unauthenticated read attempt from outside should always fail.

The Firebase Misconfigurations 2024 case shows the cost of skipping these steps: sites had "no security rules enabled or had set them up incorrectly", most also allowed writes, and about 20 million passwords were exposed, nearly all in plaintext fields the site operators had added themselves.

Metrics:

  1. Production projects with any rule granting unconditioned read or write, target zero.
  2. Percentage of collections and storage paths covered by at least one negative rules test.
  3. Ruleset releases made outside the pipeline, target zero.
  4. Percentage of client traffic verified by App Check on enforced services.
  5. Time from a failed external unauthenticated-access check to fix.

Hardening baseline

  1. Inventory: list every Firebase project, its Firestore, Realtime Database instances and Storage buckets, and the current rules. Flag test-mode and open rules immediately.
  2. Emergency close: for any open production rule, deploy a locked ruleset for unused paths at once and owner-only rules for user data, accepting a short outage over continued exposure. Keep the previous ruleset in version control for rollback.
  3. Model data for rules: separate public and private data into different collections or paths, and put ownership and role fields where clients cannot change them.
  4. Write tests: add the negative tests above, run them in CI against the Emulator Suite, and block deploys on failure.
  5. Pipeline deploys: remove console rule editing rights in production; deploy from the repository through the Firebase CLI.
  6. App Check: enable in monitoring mode, review metrics until legitimate traffic is verified, then enforce product by product. Roll back by switching enforcement off for that product.
  7. Authentication settings: enable email enumeration protection, require verified email or non-anonymous sign-in in rules that protect non-public data, and tighten identity toolkit quotas.
  8. Monitor: budget alerts, alerts on ruleset releases and a scheduled external unauthenticated-access check.

Small versus large teams: a solo developer should at minimum use deny-by-default, owner-only rules and a handful of emulator tests. Larger teams should require security review of rules changes, keep shared helper functions in a reviewed library, and treat a rules regression as a release-blocking defect.

Framework mapping

ControlOWASPNIST SP 800-53 Rev 5CIS Controls v8.1
Owner and role checks in rulesAPI1:2023 Broken Object Level Authorization; MASVS-AUTHAC-3 Access Enforcement; AC-6 Least Privilege3.3 Configure Data Access Control Lists
Field validation on writesAPI3:2023 Broken Object Property Level AuthorizationSI-10 Information Input Validation16 Application Software Security
Query limits, App Check, budgetsAPI4:2023 Unrestricted Resource ConsumptionSC-5 Denial-of-Service Protection13 Network Monitoring and Defense
Emulator tests in CIOWASP ASVS access control requirementsSA-11 Developer Testing and Evaluation16.12 Implement Code-Level Security Checks
Pipeline-only rules deploysAPI8:2023 Security MisconfigurationCM-3 Configuration Change Control4.1 Establish and Maintain a Secure Configuration Process

Common misconfigurations

  • Test mode left on: rules created by the console's test mode shipped to production.
  • Authenticated equals authorised: request.auth != null on everything, combined with open self-registration, which is how researchers got full database access in the earlier Chattr case cited in the Firebase exposure research.
  • Recursive wildcards: a {document=**} grant that silently overrides every narrower rule below it.
  • Client-editable roles: an isAdmin field on the user's own profile document, writable by that user.
  • Queries that rely on rules to filter: developers loosen rules because constrained queries "failed", instead of adding the matching where clause.
  • Storage forgotten: Firestore locked down while the Storage bucket still allows read, write with no condition, exposing uploaded documents and images.

Practitioner checklist

  • Start every ruleset deny-by-default with rules_version = '2'; and open only named paths.
  • Replace any request.auth != null-only rule with uid, claim or field conditions.
  • Protect owner and role fields on update and keep roles in backend-written documents or custom claims.
  • Validate keys, types and sizes of incoming data on create and update.
  • Constrain queries to match rules and require limits on list requests.
  • Unit test rules with @firebase/rules-unit-testing and the Emulator Suite in CI, starting with negative tests.
  • Deploy rules only from version control through the pipeline; alert on other releases.
  • Enforce App Check on Firestore, Realtime Database, Storage and callable functions after a monitoring period.
  • Review Storage and Realtime Database rules as carefully as Firestore.
  • Run a scheduled unauthenticated access check against every production project.

Standards and references

Related NHI Mgmt Group resources: Firebase Credentials Security Guide · Firebase Misconfigurations 2024 · Mobile App Security Guide · Google Cloud Security Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 27 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org