Los fallos de seguridad de las aplicaciones generadas con IA no son aleatorios. Se repiten con una regularidad que sorprende hasta que entiendes de dónde vienen: un asistente de código optimiza para que veas algo funcionando cuanto antes, y en el camino más corto entre «no hay nada» y «funciona» no hay control de acceso, ni límites, ni gestión de secretos.
Este es el catálogo de lo que aparece una y otra vez, ordenado por lo que cuesta cuando pasa. De cada uno: qué es, cómo lo detectas tú mismo y cómo se corrige. La lista vale igual para Lovable, Bolt, v0, Replit, Base44 o código escrito a mano con Cursor o Copilot.
Esta guía la firma Miguel Quílez, director de Hiberus Booster, la unidad del grupo Hiberus especializada en inteligencia artificial. Hiberus es la primera consultora tecnológica española de capital privado, con más de 4.000 profesionales.
Familia 1 — Los datos están abiertos
1. Reglas de acceso por fila desactivadas
Qué es. La aplicación habla directamente con la base de datos desde el navegador. Lo único que impide que un usuario pida la tabla entera son las reglas por fila (Row Level Security en Supabase). Durante el desarrollo estorban, se desactivan, y nadie vuelve a activarlas.
Cómo lo detectas. Panel de Supabase, sección de tablas: busca las marcadas como «Unrestricted» o «RLS disabled».
Cómo se corrige. Activar RLS en toda tabla con datos de personas y escribir una política por operación (lectura, inserción, actualización, borrado). Después, probar con dos cuentas distintas que ninguna ve los datos de la otra.
2. Reglas activadas pero mal escritas
Qué es. El caso más traicionero, porque el panel se ve verde. La política dice «permite a cualquier usuario autenticado» en vez de «permite al dueño de la fila». Cualquiera que se registre ve los datos de todos.
Cómo lo detectas. Lee la política. Si no compara el identificador del usuario de la sesión con una columna de la fila, está mal.
Cómo se corrige. Reescribir la condición para que ate cada fila a su propietario, y probarlo con dos cuentas reales. Nunca se da por buena una política sin la prueba cruzada.
3. Endpoints internos sin comprobación de permisos
Qué es. La pantalla de administración solo se ve si eres administrador —en el navegador—. Pero la dirección que consulta esa pantalla responde a cualquiera que la escriba. Esconder el botón no es proteger la puerta.
Cómo lo detectas. Abre las herramientas de desarrollo, mira qué direcciones consulta la pantalla de administración y pégalas en una ventana de incógnito.
Cómo se corrige. Comprobar el rol en el servidor, en cada punto de entrada, antes de devolver nada.
Familia 2 — Las llaves están fuera
4. Clave de servicio en el navegador
Qué es. La clave de servicio (service role) se salta todas las reglas por diseño. Cuando un asistente resuelve un problema de permisos usándola desde el lado del cliente —porque así funciona a la primera—, esa clave viaja al navegador de todos tus usuarios. Quien la copie tiene control total de la base de datos.
Cómo lo detectas. Ver el código fuente de la página y buscar «service_role». También revisa el historial del repositorio: una clave borrada hace tres commits sigue estando ahí.
Cómo se corrige. Rotar la clave de inmediato —está comprometida—, moverla al servidor y volver a llamarla solo desde funciones que corren fuera del navegador.
5. Claves de modelos de IA y de pago expuestas
Qué es. Lo mismo, con la factura como daño inmediato. Una clave de OpenAI o Anthropic en el cliente es un gasto abierto a nombre de cualquiera. Una clave de la pasarela de pago es peor.
Cómo lo detectas. Busca en el código del navegador las cadenas típicas de cada proveedor y cualquier variable que empiece por algo parecido a «secret». Si tu configuración usa un prefijo público para exponer variables al cliente, revisa una por una cuáles están marcadas así.
Cómo se corrige. Toda llamada a un proveedor de pago por uso pasa por una función en el servidor. El navegador llama a tu función; tu función llama al proveedor.
6. Secretos en el repositorio
Qué es. El archivo de variables de entorno acaba subido al repositorio porque nadie escribió la línea que lo excluye. Si el repositorio es público, la clave se indexa en minutos.
Cómo lo detectas. Revisa qué archivos están versionados y busca los nombres habituales de archivos de entorno en el historial completo, no solo en el estado actual.
Cómo se corrige. Rotar todo lo expuesto, excluir esos archivos y guardar los secretos en el gestor de variables de la plataforma. Borrar el archivo en un commit nuevo no limpia el historial.
Familia 3 — No hay límites
7. Sin límite de peticiones
Qué es. Un formulario público que alguien puede enviar diez mil veces por minuto. Si detrás hay un modelo de IA, cada envío cuesta dinero; si hay un correo, tu dominio acaba marcado como spam; si hay un registro, tu base de datos se llena de basura.
Cómo lo detectas. Envía el mismo formulario veinte veces seguidas. Si las veinte pasan, no hay límite.
Cómo se corrige. Límite por dirección y por usuario en los puntos de entrada que cuestan dinero, más una comprobación anti-robots en los formularios abiertos.
8. Sin tope de gasto
Qué es. El complemento del anterior. Ningún proveedor de pago por uso viene con tope configurado; el defecto es que sigas gastando.
Cómo lo detectas. Entra en la facturación de cada proveedor que uses y comprueba si hay un límite mensual y una alerta por correo.
Cómo se corrige. Configurar tope duro y alerta al 50 % en cada proveedor. Cinco minutos por proveedor, una sola vez.
9. Validación solo en el formulario
Qué es. El campo del navegador comprueba que el precio sea positivo y que el correo tenga arroba. Nada de eso viaja al servidor: la validación del navegador es comodidad para el usuario, no seguridad. Quien envíe la petición a mano manda lo que quiera.
Cómo lo detectas. Comprueba si existe validación en el lado del servidor. Si el punto de entrada acepta el cuerpo tal cual y lo inserta, no la hay.
Cómo se corrige. Validar en el servidor con un esquema explícito: tipos, rangos, longitudes y campos permitidos. La validación del navegador se queda, pero como ayuda visual.
Familia 4 — El día que falle
10. Copias de seguridad que nunca se han restaurado
Qué es. La plataforma hace copias automáticas y eso tranquiliza. Una copia que nunca se ha restaurado no es una copia: es una suposición. Se descubre el día que hace falta, que es el peor día posible.
Cómo lo detectas. Pregúntate cuánto tardarías en tener la aplicación funcionando otra vez si la base de datos desapareciera ahora. Si no tienes el número, no lo has probado.
Cómo se corrige. Restaurar una copia en un entorno aparte, cronometrarlo y anotar el procedimiento. Repetirlo cada trimestre.
Qué pesa más y en qué orden se arregla
| Error | Qué pasa si no se toca | Urgencia |
|---|---|---|
| 1 y 2 — Reglas de acceso | Fuga completa de datos de clientes | Inmediata |
| 4 y 5 — Claves expuestas | Control total de la base de datos o factura ajena | Inmediata |
| 6 — Secretos en el repositorio | Lo mismo, con la clave indexada por buscadores | Inmediata |
| 3 — Endpoints sin permisos | Un usuario cualquiera actúa como administrador | Alta |
| 9 — Validación solo en cliente | Datos corruptos, precios manipulados | Alta |
| 7 y 8 — Sin límites | Factura desbocada, dominio quemado | Media |
| 10 — Copias sin probar | Pérdida irreversible el día del incidente | Media |
Los seis primeros se arreglan en días y no requieren rehacer nada. Si tu aplicación tiene varios de la mitad de arriba y ya hay clientes usándola, el orden correcto es taparlos antes de añadir una sola funcionalidad nueva.
Preguntas frecuentes
¿Cuáles son los errores de seguridad más frecuentes en apps hechas con IA?
Diez, agrupados en cuatro familias: reglas de acceso por fila desactivadas o mal escritas y endpoints internos sin comprobar permisos; clave de servicio, claves de IA o de pago expuestas en el navegador y secretos subidos al repositorio; ausencia de límite de peticiones, de tope de gasto y de validación en el servidor; y copias de seguridad que nunca se han restaurado.
¿Por qué se repiten siempre los mismos fallos?
Porque un asistente de código optimiza para que veas algo funcionando cuanto antes, y el camino más corto entre no tener nada y tener algo que funciona no pasa por el control de acceso, los límites ni la gestión de secretos. No es un defecto de una herramienta concreta: pasa igual en Lovable, Bolt, v0, Replit o en código escrito con Cursor.
¿Cómo sé si mi base de datos está abierta?
En el panel de Supabase, sección de tablas, busca las marcadas como «Unrestricted» o «RLS disabled». Si alguna con datos de personas aparece así, cualquiera puede leerla desde la consola del navegador. Y aunque estén activadas, hay que leer la política: si no compara el identificador del usuario con una columna de la fila, deja la puerta igual de abierta.
¿Qué hago si he expuesto una clave de servicio?
Rotarla de inmediato: desde el momento en que viajó al navegador está comprometida, y borrarla del código no la invalida. Después, moverla al servidor y llamarla solo desde funciones que corran fuera del navegador. Lo mismo vale para una clave subida al repositorio, incluso si la borraste en un commit posterior: el historial la conserva.
¿Cuál de estos errores debo arreglar primero?
Los de fuga de datos y claves: reglas de acceso, clave de servicio expuesta y secretos en el repositorio. Son de urgencia inmediata porque suponen acceso completo a los datos de tus clientes. Después van los endpoints sin comprobación de permisos y la validación solo en cliente; los límites de gasto y las copias sin probar son urgencia media.
¿Cuánto se tarda en corregirlos?
Los seis primeros se resuelven en días y no obligan a rehacer nada: son configuración y comprobaciones en el servidor, no arquitectura. Si tu aplicación tiene varios y ya hay clientes usándola, lo sensato es taparlos antes de añadir ninguna funcionalidad nueva.
¿La validación del formulario no es suficiente?
No. La validación en el navegador es comodidad para el usuario, no seguridad: quien envíe la petición a mano manda lo que quiera. Hace falta validar en el servidor con un esquema explícito de tipos, rangos, longitudes y campos permitidos.
¿Sirve esta lista para código escrito con Cursor o Copilot?
Sí. Cambia la superficie —tienes el código delante y puedes revisarlo— pero los patrones son los mismos, porque el modelo que sugiere el código optimiza igual. La diferencia es que con Cursor la corrección suele ser más rápida, ya que controlas todo el proyecto.
¿Cuántos de estos diez tiene tu aplicación?
Cuéntanos qué has construido y con qué herramienta. Te decimos en 24 horas cuáles de estos fallos encontraríamos y cuáles son urgentes.
✓ ¡Recibido!
Gracias. Un especialista de Hiberus Booster te contacta en menos de 24 horas.