CVE-2025-48757 es una vulnerabilidad de Lovable con puntuación crítica (CVSS 9.3) que dejó expuestas más de 170 aplicaciones. El problema: cualquier persona, sin iniciar sesión, podía leer —y en muchos casos modificar— datos de tu base de datos: nombres, emails, claves de API de terceros e incluso el estado de los pagos. La causa no es un bug oculto de Lovable, sino un patrón que comparten casi todas las apps "vibe-coded": confiar toda la seguridad de la base de datos a las políticas RLS de Supabase… y dejarlas incompletas.
Qué pasó exactamente
Lovable genera apps donde el navegador habla directamente con la base de datos (Supabase) mediante llamadas REST, usando la clave pública anon. Eso está bien diseñado siempre que cada tabla tenga políticas de Row-Level Security (RLS) que decidan qué filas puede ver o tocar cada usuario. La vulnerabilidad apareció porque muchos proyectos se desplegaban con tablas sin RLS o con RLS insuficiente. Un atacante solo tenía que editar la petición REST —cambiar un filtro en la URL— para pedir "todas las filas" de una tabla que debería estar protegida.
Fue reportada en marzo de 2025 por Matt Palmer y Kody Low, y de forma independiente por Danial Asaria, con divulgación pública el 29 de mayo de 2025 (detalle técnico del reporte, ficha CVE). Cualquier proyecto de Lovable con base de datos creado antes del 15 de abril de 2025 podía estar afectado.
Por qué te afecta aunque no uses Lovable
Este no es un problema exclusivo de Lovable. Cualquier app que hable directamente con Supabase desde el navegador —da igual si la montaste con Bolt, v0, Cursor o a mano— depende de que RLS esté bien puesto en todas las tablas. La app se ve perfecta, el login funciona, pero la seguridad de verdad vive en la base de datos, no en la interfaz. Ocultar un botón en el frontend no protege nada: la petición REST sigue ahí para quien sepa mirar.
Cómo saber si tu app es vulnerable
- Abre las DevTools (F12) → pestaña Network mientras usas tu app y mira las llamadas a
*.supabase.co/rest/v1/. Copia una de esas URLs, ábrela en una ventana de incógnito (sin sesión) y mira si te devuelve datos. - Prueba a pedir "de más": si una llamada trae tus datos, quita el filtro de la URL. Si te devuelve filas de otros usuarios, no tienes RLS efectivo.
- Revisa el panel de Supabase → Authentication → Policies. Cualquier tabla con datos reales y el aviso "RLS disabled" o sin ninguna política es una puerta abierta.
Cómo arreglarlo
- Activa RLS en todas las tablas, no solo en las "importantes". La regla es denegar por defecto: sin política que lo permita, nadie accede.
- Escribe políticas explícitas por operación (select/insert/update/delete) atadas a
auth.uid(), para que cada usuario solo toque sus propias filas. - Nunca uses la clave
service_roleen el frontend: salta RLS por completo. Esa clave vive solo en el servidor. - Vuelve a probar con el paso de incógnito de arriba: si ahora la petición sin sesión devuelve vacío o un error, vas bien.
Cómo lo comprueba Scanaris
Scanaris analiza tu web en modo solo-lectura y detecta la huella de este patrón: endpoints de Supabase accesibles desde el navegador, CORS permisivo, claves y tokens expuestos en el JavaScript y datos que la app sirve sin sesión. Pega tu URL y te dice, en segundos y ordenado por gravedad, qué está a la vista de cualquiera —antes de que lo encuentre otro.