Volver al blog
14 de agosto de 2026

Firebase Security Rules Left Wide Open: allow read, write: if true

Viktor Bulanek
Founder & CTO, Penetrify
MSc IT Security · 20+ years in security · 4x Ex-CTO

Firestore and Realtime Database are not protected by your application. They are protected by rules that live in the database and are evaluated on every request, because the client talks to the database directly. Get the rules wrong and there is no server-side code to save you — the security boundary is the rule file, and nothing else.

The most common way to get it wrong is not subtle. It is allow read, write: if true;, left in place from the day the project was created.

How the Default Becomes Production

When you create a Firestore database, the console offers test mode and production mode. Test mode writes a rule that allows all reads and writes for thirty days, and it exists for a good reason: it lets you build without fighting permissions while nothing real is in the database.

Then the thirty days lapse, the app breaks, and the fastest fix — the one every tutorial and Stack Overflow answer suggests — is to change the timestamp condition to if true. Development continues. The app ships. The rule is still there, and now it guards real customer data.

The pattern concentrates in a specific kind of project: mobile and web MVPs built quickly, often with Flutter or React Native, frequently by teams whose strength is product rather than backend. Firebase is popular precisely because it removes the backend, and removing the backend also removes the place where authorisation normally lives. That trade is fine as long as the rules take up the job, and the rules are the first thing to be postponed.

What "Wide Open" Actually Exposes

Your Firebase project ID is not a secret — it is in your client bundle and in your mobile app, because the client needs it to connect. With the ID and an open rule, anyone can query the database over the public REST and SDK endpoints without touching your application at all.

Read access means the entire collection tree: user documents, order history, chat messages, uploaded file references, any admin collection you created for internal tooling. Write access means creating and modifying documents — changing a subscription field, editing a price, inserting content that your app will render to other users, or deleting collections outright.

Two consequences catch teams by surprise. First, your application's own validation is irrelevant, because requests never pass through it: a field your UI would never send is accepted if the rule permits the write. Second, your billing is exposed — Firestore charges per document read, so an open database is not only a data breach but a cost incident, and a script iterating your collections can run a bill up fast.

Storage rules deserve the same look. The same permissive pattern in storage.rules makes every uploaded file readable, and lets an attacker replace a file with one of their own choosing.

The Failure Modes That Look Secure and Are Not

Beyond if true, three rule patterns pass a glance and fail a test.

Authenticated is not authorised. allow read, write: if request.auth != null; is the second most common rule we see, and it means any signed-in user can read and write everything — including other users' documents. If your app allows self-service signup, this is functionally open to the internet with one extra step.

Ownership checked on read, not on write. Rules are often written carefully for read and loosely for write, because reads are what the developer was debugging. The result is a database where you cannot see someone else's document but you can overwrite it.

Validation missing on shape. Even a correct ownership rule permits a user to write arbitrary fields into their own document — including role: "admin" or plan: "enterprise", if your application trusts those fields. Rules can constrain the shape of a write with request.resource.data, and most rule files never do.

How to Check Your Own Project

Read the rules first, in the Firebase console under Firestore or Realtime Database, and again under Storage. If you see if true, or a bare request.auth != null on a collection holding user data, you have your answer without testing anything.

Then test empirically, because the rules you deployed are not always the rules you have in your repository. Create two ordinary user accounts, and from account A attempt to read and write a document belonging to account B:

# Firestore REST, as an authenticated user
curl -H "Authorization: Bearer <id-token-for-user-A>" \
  "https://firestore.googleapis.com/v1/projects/<project-id>/databases/(default)/documents/users/<user-B-doc-id>"

Any response other than a permission error is a finding. Repeat without a token at all, which tests the unauthenticated path, and repeat for writes rather than assuming they mirror reads. The Firebase emulator suite runs the same rules locally, so these checks belong in your test suite rather than in a periodic audit.

The Fix

Write rules that assert ownership and shape, per collection, and deny by default. The general form is unglamorous and effective:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId;
      allow update: if request.auth != null && request.auth.uid == userId
        && !request.resource.data.diff(resource.data).affectedKeys()
             .hasAny(['role', 'plan', 'credits']);
    }
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Three things are doing the work there: ownership is checked against the authenticated UID rather than against a field in the document, privileged fields are explicitly excluded from what a user may change, and the catch-all at the end denies anything you forgot to write a rule for. That last clause is the one that converts an incomplete rule file from dangerous to merely incomplete.

Then move rules into CI. They are a text file in your repository, the emulator can evaluate them, and a test that asserts "user A cannot read user B's document" is a few lines. Rules that are only reviewed when something breaks will drift, because every new collection is a new opportunity to forget.

Why This Keeps Happening

Because the platform's greatest strength is also where it puts the sharpest edge. Firebase lets a small team ship a real product without a backend, and in exchange it asks them to implement authorisation in a declarative language they will use once and then not touch for a year. The permissive rule is not laziness; it is the only state in which the tutorial works.

It also fails silently in the direction of working. An over-permissive rule never produces an error, never breaks a build, and never appears in a bug report — the app functions perfectly, for everyone, including people who are not your users. That combination is why this class survives code review and lands in automated testing instead: a scan can hold two accounts and try the thing your rules were supposed to prevent, which is the only way to know they do.

Frequently Asked Questions

¿Qué tipos de vulnerabilidades detecta Penetrify?

Penetrify detecta todas las categorías de vulnerabilidades del OWASP Top 10, incluyendo inyección SQL, XSS, CSRF, IDOR, autenticación rota, configuraciones de seguridad incorrectas y exposición de datos sensibles. También prueba la seguridad de APIs, la gestión de sesiones y configuraciones incorrectas comunes en Supabase, Firebase y Bubble.

¿Cuánto tiempo dura un test de penetración con IA?

Un escaneo rápido se completa en 15–30 minutos. Un escaneo estándar dura 1–2 horas con mayor cobertura. Un escaneo profundo puede durar varias horas en aplicaciones complejas.

¿Qué incluye un informe de Penetrify?

Cada informe incluye un resumen ejecutivo, una puntuación general de seguridad, hallazgos clasificados por severidad (Crítico, Alto, Medio, Bajo), pasos de reproducción detallados y orientación concreta de remediación escrita para desarrolladores, no para responsables de cumplimiento.

Related articles

Detén los cuellos de botella de DevSecOps con pruebas de seguridad automatizadas
Detenga los cuellos de botella de DevSecOps que ralentizan su pipeline. Descubra cómo las pruebas de seguridad automatizadas permiten un verdadero "shift left" sin sacrificar la velocidad. ¡Lea más ahora!
La clave secreta de Stripe en el paquete de frontend: 4 meses de exposición silenciosa
Un equipo de dos personas construyó un marketplace en Bubble.io que procesaba más de $40,000 en pagos. Su clave secreta de la API de Stripe había estado en el paquete JavaScript del lado del cliente durante cuatro meses, lo que otorgaba a cualquiera que la encontrara acceso completo de lectura/escritura a toda su infraestructura de pagos. Así fue como sucedió, qué estuvo en riesgo y qué hicieron al respecto.
Análisis de Cumplimiento PCI DSS: La Guía 2026 para la Seguridad Automatizada
El 14 de marzo de 2025, un minorista de primer nivel descubrió que una simple regla de firewall mal configurada durante un *push* del viernes por la tarde invalidó tres meses de preparación para el cumplimiento normativo en menos de seis minutos. Seguramente ya sabrá que los escaneos trimestrales tradicionales de cumplimiento PCI DSS se sienten como revisar el velocímetro...

Explore more