← Blog
·8 min read

Firebase Security Rules: Los Errores Más Comunes (y Cómo Evitarlos)

firebase rules errores que dejan tus datos expuestos: read: true global, sin validación de datos, reglas que nunca aplican. Con ejemplos y fixes reales.

Rod

Founder & Developer

Firebase rules errores — hay uno en particular que aparece en casi todos los repos nuevos que escaneamos: allow read, write: if true. Esa línea deja tu base de datos completamente abierta a cualquiera en internet. No necesitan tu app. No necesitan estar autenticados. Solo necesitan el ID de tu proyecto, que está visible en tu código fuente.

Este no es el único error. Es el más obvio. Los otros son más sutiles y por eso duran más tiempo sin detectarse.


Por qué las Firebase Security Rules son diferentes a lo que imaginas

Las Firebase Security Rules no son código que corre en tu servidor. Son reglas declarativas que Firebase evalúa en el momento en que alguien intenta leer o escribir datos. Si no tienes reglas — o si tus reglas dicen "permite todo" — cualquiera puede acceder a tu base de datos directamente desde el browser.

Esto es diferente a cómo funciona una API tradicional. Con una API REST, pones la lógica de autorización en tu servidor. Con Firebase, el cliente habla directo con la base de datos. Las reglas son lo único que está entre tus datos y el mundo.

El SDK de Firebase para el cliente incluye tu configuración del proyecto — apiKey, projectId, databaseURL. Esos valores son públicos por diseño. No son el problema. El problema es dejar las reglas abiertas.


Error 1: allow read, write: if true — la regla que no deberías tener nunca

// MAL: cualquier persona puede leer y escribir todos tus datos
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true; // <- esto es una base de datos pública
    }
  }
}

Esta regla viene por default en el modo "test" cuando creas un proyecto nuevo de Firebase. El problema es que muchos proyectos llegan a producción con esta configuración intacta.

Con allow read, write: if true en producción:

  • Cualquier persona puede leer todos tus documentos
  • Cualquier persona puede sobrescribir o borrar cualquier documento
  • Cualquier persona puede crear documentos con cualquier estructura
// BIEN: denegar todo por default, permitir solo lo necesario
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Denegar todo por default
    match /{document=**} {
      allow read, write: if false;
    }
 
    // Permitir a usuarios autenticados leer sus propios datos
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

La regla base siempre debe denegar. Agrega permisos específicos por colección.


Error 2: Verificar autenticación sin verificar permisos

Verificar que un usuario está autenticado no es lo mismo que verificar que tiene permiso sobre ese documento específico.

// MAL: cualquier usuario autenticado puede leer cualquier perfil
match /users/{userId} {
  allow read: if request.auth != null; // autenticado != autorizado
}

Con esta regla, el usuario A puede leer el perfil completo del usuario B. Solo necesita conocer el ID del documento — y en Firestore, los IDs de documento a menudo son predecibles o se filtran por otras vías.

// BIEN: solo el dueño del documento puede leerlo
match /users/{userId} {
  allow read: if request.auth != null && request.auth.uid == userId;
}
 
// O si quieres que cualquier usuario autenticado pueda ver perfiles pero no datos sensibles:
match /users/{userId} {
  allow read: if request.auth != null; // perfil público entre usuarios
}
match /users/{userId}/private/{doc} {
  allow read: if request.auth.uid == userId; // datos sensibles solo para el dueño
}

La distinción entre autenticación ("¿quién eres?") y autorización ("¿qué puedes hacer?") es fundamental. Las reglas de Firebase pueden hacer las dos cosas — tienes que configurarlas para eso.


Error 3: No validar la estructura de los datos al escribir

Firebase te deja guardar cualquier cosa en un documento. Si no validas qué campos se pueden escribir, un usuario puede agregar campos arbitrarios, sobrescribir campos que no debería tocar, o meter tipos de datos incorrectos.

// MAL: cualquier usuario autenticado puede escribir cualquier cosa en su documento
match /users/{userId} {
  allow write: if request.auth.uid == userId;
}

Con esto, un usuario puede agregarse el campo isAdmin: true a su propio documento — y si tu app lee ese campo para decidir permisos, tienes un problema serio.

// BIEN: validar qué campos puede escribir un usuario y de qué tipo
match /users/{userId} {
  allow update: if request.auth.uid == userId
    && request.resource.data.keys().hasOnly(["displayName", "bio", "photoURL"])
    && request.resource.data.displayName is string
    && request.resource.data.displayName.size() <= 100;
}

request.resource.data es el documento que el usuario intenta escribir. resource.data es el documento actual. Con estas dos referencias puedes validar qué campos cambian y con qué valores.


Error 4: Reglas que nunca aplican por el orden de los match

Las reglas de Firebase se evalúan de arriba a abajo dentro de un match, pero si tienes una regla que ya permite el acceso, las reglas más específicas de abajo no niegan ese acceso.

// MAL: la regla general de arriba permite todo, la específica de abajo nunca aplica
match /databases/{database}/documents {
  match /{document=**} {
    allow read: if request.auth != null; // permite a cualquier usuario autenticado
  }
  match /admin/{doc} {
    allow read: if request.auth.token.admin == true; // nunca se evalúa
  }
}

Firebase usa la regla más permisiva que aplica. Si la regla general ya permite el acceso, las reglas más específicas no pueden restringirlo.

// BIEN: la regla general deniega, permisos específicos por colección
match /databases/{database}/documents {
  match /{document=**} {
    allow read, write: if false; // denegar todo por default
  }
  match /publicPosts/{postId} {
    allow read: if true; // posts públicos, cualquiera puede leer
  }
  match /admin/{doc} {
    allow read, write: if request.auth.token.admin == true; // solo admins
  }
  match /users/{userId}/posts/{postId} {
    allow read, write: if request.auth.uid == userId; // solo el dueño
  }
}

Error 5: Confiar en datos del cliente para decisiones de seguridad

Un patrón peligroso: guardar el rol del usuario en el documento de Firestore y luego leer ese campo en las reglas.

// MAL: leer el rol desde el documento — el usuario puede modificarlo
match /posts/{postId} {
  // request.auth.uid == get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role
  // No hagas esto — el usuario puede cambiar su propio campo "role"
  allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "editor";
}

Si el usuario puede escribir en su propio documento de /users, puede cambiarse el campo role a lo que quiera.

// BIEN: usar custom claims del token de Firebase Auth
match /posts/{postId} {
  allow write: if request.auth.token.role == "editor";
}

Los custom claims se setean desde el servidor con Firebase Admin SDK y no pueden ser modificados por el usuario. Úsalos para roles y permisos críticos.

Para setear un custom claim desde un servidor o Cloud Function:

// En tu servidor con Firebase Admin SDK
await admin.auth().setCustomUserClaims(uid, { role: "editor" });

Cómo revisar tus reglas actuales

Firebase tiene un simulador de reglas en la consola: Firestore > Rules > Rules Playground. Ahí puedes simular lecturas y escrituras como usuario autenticado o no autenticado y ver si tus reglas permiten o deniegan correctamente.

El flujo que recomendamos:

  1. Simula una lectura sin autenticación — debería denegar
  2. Simula una lectura con un usuario que no es el dueño del documento — debería denegar
  3. Simula una escritura con campos que no deberían estar permitidos — debería denegar
  4. Simula las operaciones legítimas que tu app hace — deben funcionar

Si tienes un repo en GitHub con tus Firebase rules, Data Hogo las escanea automáticamente y reporta configuraciones peligrosas como parte del análisis de seguridad.

Escanea tu repo gratis — incluyendo Firebase rules →


Regla de oro para Firebase Security Rules

Denegar todo por default. Permitir solo lo que tu app necesita específicamente. Validar la estructura de los datos al escribir. Usar custom claims para roles, no campos de Firestore.

Si sigues esos cuatro principios, evitas el 95% de los problemas que vemos en repos reales.

Para profundizar en seguridad de bases de datos más allá de Firebase, nuestra guía de ciberseguridad para programadores principiantes cubre los conceptos base que aplican a cualquier stack. Y si usas Supabase en lugar de Firebase, los mismos principios aplican — con Row Level Security en lugar de Security Rules.


Preguntas frecuentes

¿Qué pasa si dejo Firebase rules con allow read, write: if true?

Cualquier persona en internet puede leer y escribir todos tus datos de Firestore sin autenticación. No necesitan tu app ni tu API key — solo necesitan el ID de tu proyecto de Firebase, que está en tu código fuente. Esta configuración es el equivalente a dejar tu base de datos completamente pública.

¿Cómo verifico si mis Firebase Security Rules están bien configuradas?

Firebase tiene un simulador de reglas en la consola (Firestore > Rules > playground). Prueba leer y escribir documentos sin autenticación y con usuarios diferentes. También puedes escanear tu proyecto con Data Hogo — el scanner analiza las reglas de Firebase y reporta configuraciones peligrosas.

¿Cuál es la regla de Firebase más segura para empezar?

La más segura para empezar es denegar todo por default y solo permitir lo que necesitas explícitamente: allow read, write: if false. Desde ahí agrega permisos específicos por colección. Es mejor agregar permisos que descubrir que diste demasiados.

¿Firebase Security Rules pueden reemplazar la validación en el servidor?

No. Las Firebase Security Rules validan en el lado de la base de datos, pero no reemplazan la lógica de negocio ni la validación en tu servidor o Cloud Functions. Úsalas como una capa de defensa adicional, no como la única.

¿Cómo restrinjo que un usuario solo pueda leer sus propios datos en Firestore?

Usa request.auth.uid en la regla y compáralo con el campo del documento que identifica al dueño. Por ejemplo: allow read: if request.auth != null && request.auth.uid == resource.data.userId. Esto garantiza que solo el dueño del documento puede leerlo.

firebasesecurity rulesfirestorebase de datosseguridadtutoriales