Firebase es el backend favorito de muchas apps hechas con IA: Lovable, Bolt o Cursor lo conectan en minutos y tienes autenticación, base de datos y archivos sin montar un servidor. El problema es que su modelo de seguridad es el contrario al de un backend tradicional. Aquí el navegador habla directamente con la base de datos, así que no hay un servidor que filtre peticiones: las reglas de seguridad son tu única barrera, y una regla mal escrita deja todos los datos a la vista. Esta guía repasa los diez errores que más se repiten, con la regla incorrecta y la correcta en cada caso, y termina con cómo comprobarlo tú mismo.
1. Reglas en modo de prueba, o lo que viene después
Al crear una base de datos, Firebase te ofrece el "modo de prueba": todo abierto durante treinta días. La regla tiene esta pinta:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.time < timestamp.date(2026, 11, 3);
}
}
}
Hasta esa fecha, cualquiera con tu projectId (que está en el código del navegador) puede leer y escribir toda la base de datos. Y lo peor viene después: al caducar, la app deja de funcionar, el desarrollador busca una solución rápida y sustituye la fecha por if true. Ahora el agujero es permanente. La solución es escribir reglas por colección desde el primer día, basadas en quién es el usuario y de quién es el documento.
2. allow read: if true en datos de usuarios
Hay colecciones que pueden ser públicas (un catálogo de productos, los posts de un blog). Pero allow read: if true en users, orders o messages significa que cualquiera puede descargar la lista completa. La forma correcta de proteger documentos por usuario:
match /users/{userId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
Cada usuario lee y escribe solo su documento. Para datos compartidos entre varios (un equipo, un proyecto) guarda la lista de miembros en el documento y compruébala en la regla.
3. Confundir "autenticado" con "autorizado"
La regla allow read: if request.auth != null parece segura y es el error más común. Dice: cualquier usuario con sesión puede leer. Pero registrarse en tu app es gratis y tarda diez segundos, así que en la práctica es lo mismo que abierto. Autenticado responde a quién eres; autorizado, a qué puedes ver. Las reglas tienen que responder a lo segundo.
4. Datos sensibles en documentos legibles
Un perfil público con nombre y avatar es razonable. El mismo documento con email, teléfono, dirección y un token de acceso, no. Si otros usuarios tienen que poder ver parte del perfil, separa lo público de lo privado en dos documentos o en una subcolección private con reglas más estrictas. Lo que no está en un documento legible no se puede filtrar.
5. Pensar que la configuración de Firebase es un secreto
El objeto con apiKey, authDomain y projectId va al navegador por diseño: identifica tu proyecto, no autoriza nada. Verlo en el código fuente no es un fallo, y no es lo que hay que esconder. Lo que sí hay que hacer con esa clave es restringirla en la consola de Google Cloud a los dominios de tu web (restricción por referente HTTP) y activar App Check, que exige que las peticiones vengan de tu app real y no de un script.
6. Otras claves sí son secretas
El error grave es otro: junto a la configuración de Firebase, el bundle lleva la clave secreta de Stripe, la de OpenAI o la de un servicio de correo porque "así era más fácil". Esas claves dan acceso a dinero y a cuentas de terceros. Su sitio es una Cloud Function con los secretos en variables de entorno, y el navegador llama a la función, nunca al servicio directamente. El detalle está en secretos que tu app filtra en el navegador.
7. Storage sin reglas propias
Cloud Storage tiene sus propias reglas y suele olvidarse. Con allow read, write: if request.auth != null cualquier usuario registrado puede leer los archivos de los demás, subir lo que quiera a cualquier ruta y llenar tu cuota. Una regla razonable limita la ruta al usuario y valida tamaño y tipo:
match /users/{userId}/{fileName} {
allow read: if request.auth != null && request.auth.uid == userId;
allow write: if request.auth != null
&& request.auth.uid == userId
&& request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*');
}
8. Realtime Database abierta
Si usas la base de datos en tiempo real en lugar de Firestore, el equivalente es ".read": true en la raíz. Las reglas son otro lenguaje, pero la lógica es la misma: nada abierto en la raíz, y permisos por rama con auth.uid.
9. Escribir sin validar
Permitir escritura al dueño del documento no basta si no validas qué escribe. Un usuario puede añadir isAdmin: true o plan: "pro" a su propio perfil desde la consola del navegador. Valida los campos con request.resource.data: qué claves existen, de qué tipo son y que los campos sensibles no cambien.
allow update: if request.auth.uid == userId
&& !request.resource.data.diff(resource.data).affectedKeys()
.hasAny(['isAdmin', 'plan', 'credits']);
10. Olvidar la factura
Firebase cobra por lectura. Una regla que permite list sin límite en una colección grande deja que un script lea millones de documentos y te genere una factura inesperada. Limita las consultas desde las reglas (request.query.limit <= 100), activa App Check y pon alertas de presupuesto en Google Cloud.
Cómo comprobarlo tú mismo
- Simulador de reglas. En la consola de Firebase, pestaña Reglas, hay un simulador donde pruebas una lectura como usuario anónimo o con un UID concreto. Prueba leer
userssin sesión: debe denegarse. - Emulador con tests. El emulador local permite escribir pruebas automáticas de reglas. Es la única forma de que no se rompan al cambiarlas.
- Desde fuera, sin token. La API REST de Firestore responde a cualquiera:
curl "https://firestore.googleapis.com/v1/projects/TU_PROYECTO/databases/(default)/documents/users"
Si devuelve documentos, esa colección está abierta. Si devuelve un error de permisos, la regla funciona. Repite con cada colección que tengas.
Scanaris revisa tu Firebase desde fuera
Scanaris detecta la configuración de Firebase en tu bundle, comprueba si las colecciones habituales responden sin autenticación, busca otras claves que no deberían estar en el navegador y revisa cabeceras, CORS y archivos expuestos. Por cada hallazgo te da un fix prompt con la regla o el cambio exacto para pegar en Lovable, Bolt o Cursor. Son comprobaciones de solo lectura sobre lo que ya es público. La lista completa de riesgos está en la guía de seguridad para Firebase, y antes de lanzar conviene repasar la checklist de seguridad.
Preguntas frecuentes
¿Es un problema que mi apiKey de Firebase esté en el código?
No por sí mismo: identifica el proyecto, no da permisos. Lo que protege los datos son las reglas. Eso sí, restringe la clave a tus dominios y activa App Check para evitar abusos.
¿Qué hago si mis reglas están abiertas ahora mismo?
Cierra primero: pon reglas por colección con request.auth.uid aunque alguna función deje de ir, y arregla la app después. Luego revisa en los registros de uso si hubo lecturas anómalas y, si había datos personales expuestos, valora si tienes que notificarlo.
¿Puedo pedirle a mi IA que escriba las reglas?
Sí, y suele hacerlo bien si le das la estructura de tus colecciones y quién debe ver qué. Pero pruébalas en el simulador antes de publicar: una IA también escribe if request.auth != null creyendo que es seguro.