Tu desarrollador abre Chrome DevTools en tu aplicación Lovable en vivo. Escribe supabase.from('users').select('*') en la consola. La consulta devuelve cada fila de usuario — correos electrónicos, niveles de suscripción, notas internas. Sin verificación de autenticación. Sin validación del servidor. Un cliente vino a nosotros el mes pasado con exactamente este escenario: una aplicación en producción, ingresos reales, y políticas de Row Level Security que no existían. Realizamos una auditoría formal. Luego auditamos cinco codebases de Lovable más. Las claves API expuestas aparecieron en el 83% de los proyectos. Las políticas RLS faltantes protegían cero tablas en cuatro de seis aplicaciones. Los patrones no eran aleatorios — eran arquitectónicos.

Séame claro: Lovable es una herramienta impresionante para prototipos. La velocidad con la que genera interfaces de usuario funcionales a partir de indicaciones de lenguaje natural es genuinamente notable. Pero hay una brecha masiva entre "prototipo funcional" y "aplicación lista para producción", y esa brecha está llena de vulnerabilidades de seguridad que la mayoría de los fundadores no técnicos ni siquiera saben buscar.

Este artículo es un desglose técnico de lo que hemos encontrado en múltiples auditorías de codebases Lovable. Si has construido algo con Lovable y estás tomando datos o dinero real de usuarios, necesitas leer esto.

Tabla de Contenidos

Auditoría de Código Lovable: Problemas de Seguridad, Brechas de RLS, y Claves API Expuestas

Lo que Lovable Realmente Genera

Lovable genera aplicaciones React (típicamente usando Vite) con Tailwind CSS y componentes shadcn/ui, conectados a un backend Supabase. El stack en sí es sólido — construimos con estas mismas herramientas regularmente en nuestro trabajo de desarrollo Next.js. El problema no es la elección de tecnología. Es cómo están conectadas.

Aquí hay una estructura de proyecto típica de Lovable:

src/
├── components/
│   ├── ui/           # componentes shadcn
│   ├── Dashboard.tsx
│   ├── Settings.tsx
│   └── ...
├── integrations/
│   └── supabase/
│       ├── client.ts  # ← Aquí es donde comienzan los problemas
│       └── types.ts
├── pages/
├── hooks/
└── lib/

El código generado es limpio y legible. Debo darle crédito a Lovable por eso. Pero la legibilidad no es igual a la seguridad. La arquitectura toma decisiones que están bien para una demostración pero son peligrosas para producción.

Seamos específicos.

El Problema de las Claves API

Cada proyecto Lovable que hemos auditado tiene credenciales de Supabase en el código del lado del cliente. Ahora, antes de que aparezcan los defensores de Supabase: sí, la clave anon está diseñada para ser pública. La documentación de Supabase lo establece explícitamente. La clave anon está destinada a ser utilizada en código del lado del cliente, y la seguridad se supone que se aplica a través de políticas de Row Level Security.

Pero aquí es donde se pone feo.

En tres de los seis proyectos que auditamos, encontramos la clave service_role de Supabase ya sea:

  1. Codificada directamente en un archivo de utilidad
  2. Almacenada en un archivo .env que fue confirmado en el repositorio de GitHub
  3. Referenciada en una Función Edge de Supabase que era accesible sin autenticación

La clave service_role ignora todas las políticas RLS. Si alguien la obtiene, tiene acceso completo de lectura/escritura a tu base de datos completa. Cada tabla. Cada fila. Datos de cada usuario.

// Patrón real que encontramos en un proyecto Lovable (claves redactadas)
import { createClient } from '@supabase/supabase-js'

// Esto estaba en un archivo llamado lib/admin.ts
// importado y usado en un componente del lado del cliente
const supabaseAdmin = createClient(
  'https://xxxxx.supabase.co',
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' // ¡clave service_role!
)

Esto no fue generado directamente por Lovable — fue agregado por el fundador cuando necesitaban funcionalidad de administrador y le pidieron a Lovable que "agregara un panel de administrador". Lovable cumplió, y como no tiene concepto de límites de seguridad lado del servidor vs. lado del cliente, puso la clave donde era conveniente.

Incluso cuando solo la clave anon está expuesta (como se pretende), el modelo de seguridad se desmorona si RLS no está configurado correctamente. Lo que nos lleva al grande.

Row Level Security: El Asesino Silencioso

Row Level Security (RLS) es el mecanismo de seguridad principal de Supabase para proteger datos a nivel de base de datos. Cuando se configura correctamente, garantiza que los usuarios solo puedan acceder a sus propios datos independientemente de qué llamadas de API se realicen desde el cliente.

Cuando auditamos los seis proyectos de Lovable, esto es lo que encontramos:

Proyecto Tablas Totales Tablas con RLS Habilitado Tablas con Políticas RLS Correctas Datos Sensibles Expuestos
Dashboard SaaS 14 6 3 PII de Usuario, datos de facturación
Aplicación de Comercio Electrónico 22 10 4 Historial de pedidos, direcciones
Rastreador de Salud 11 4 2 Registros de salud, medicamentos
Gestor de Proyectos 18 8 5 Datos de clientes, documentos
Plataforma de Reservas 16 7 3 Información de contacto, horarios
Herramienta CRM 20 9 4 Datos de clientes, notas

Lee eso de nuevo. En la aplicación de rastreador de salud — que almacenaba información real de medicamentos y salud — solo 2 de 11 tablas tenían políticas RLS correctas. Alguien con la clave anon (que es pública, recuerda) podría consultar los registros de salud de cada usuario.

Los fallos de RLS más comunes que vemos:

Políticas Completamente Faltantes

Lovable a menudo crea tablas sin habilitar RLS en absoluto. En Supabase, RLS está deshabilitado por defecto en nuevas tablas, lo que significa que cualquiera con la clave anon puede leer todos los datos.

-- Lo que a menudo encontramos: RLS no está ni siquiera habilitado
CREATE TABLE public.user_profiles (
  id UUID REFERENCES auth.users,
  full_name TEXT,
  email TEXT,
  phone TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Sin ALTER TABLE ... ENABLE ROW LEVEL SECURITY;
-- Sin políticas definidas

Políticas Demasiado Permisivas

Cuando Lovable agrega RLS, las políticas a menudo son demasiado amplias:

-- Política común generada por Lovable
CREATE POLICY "Los usuarios pueden ver todos los perfiles"
  ON public.user_profiles
  FOR SELECT
  USING (true);  -- Esto permite que CUALQUIER usuario autenticado lea TODOS los perfiles

La solución debería ser:

-- Cómo debería verse
CREATE POLICY "Los usuarios pueden ver su propio perfil"
  ON public.user_profiles
  FOR SELECT
  USING (auth.uid() = id);

Políticas DELETE y UPDATE Faltantes

Incluso cuando las políticas SELECT son correctas, las políticas INSERT/UPDATE/DELETE frecuentemente faltan o son incorrectas. Encontramos casos donde cualquier usuario autenticado podía actualizar el perfil de cualquier otro usuario.

Auditoría de Código Lovable: Problemas de Seguridad, Brechas de RLS, y Claves API Expuestas - arquitectura

Brechas de Autenticación y Autorización

Lovable maneja la autenticación básica razonablemente bien — configura Supabase Auth con correo electrónico/contraseña o inicios de sesión sociales, y los flujos de inicio/registro generalmente funcionan. Pero autenticación (¿quién eres?) y autorización (¿qué puedes hacer?) son cosas diferentes.

La capa de autorización casi siempre está incompleta o no existe.

Considera una aplicación SaaS multiinquilino. Los usuarios pertenecen a organizaciones. Solo deberían ver datos de su organización. Podrían tener diferentes roles (administrador, miembro, visualizador). Lovable no genera nada de esto.

Lo que típicamente encontramos:

// Obtención de datos generada por Lovable
const { data: projects } = await supabase
  .from('projects')
  .select('*')
  // Sin filtro para organization_id
  // Sin verificación del rol del usuario o permisos

La solución requiere cambios tanto a nivel de base de datos (RLS) como a nivel de aplicación. Necesitas una tabla memberships que asigne usuarios a organizaciones con roles, políticas RLS que verifiquen membresía, y código de aplicación que filtre apropiadamente.

Este es el tipo de trabajo de arquitectura que es difícil de agregar después. Toca cada consulta, cada componente, cada página. Si estás construyendo un SaaS multiinquilino con Lovable, esta es la cosa que te morderá más fuerte.

Exposición de Lógica de Negocio del Lado del Cliente

Porque Lovable genera aplicaciones React puras del lado del cliente, toda la lógica de negocio vive en el navegador. Esto significa:

  • Los cálculos de precios son visibles y manipulables en DevTools del navegador
  • Las banderas de características para diferentes niveles de suscripción se verifican del lado del cliente
  • Los códigos de descuento y la lógica de validación están en el paquete de JavaScript
  • El limitador de velocidad de API no existe (no hay servidor para aplicarlo)

Encontramos un SaaS generado por Lovable donde la verificación del nivel de precios era completamente del lado del cliente:

// Encontrado en un componente del proyecto Lovable
const canAccessFeature = (feature: string) => {
  const plan = user?.subscription?.plan
  if (plan === 'pro') return true
  if (plan === 'basic' && BASIC_FEATURES.includes(feature)) return true
  return false
}

Un usuario podría simplemente modificar esta función en la consola del navegador — o llamar directamente a la API de Supabase sin esta verificación — y acceder a características pro en un plan básico. La base de datos no tenía políticas para aplicar el acceso basado en el plan.

Este es un problema arquitectónico fundamental. La lógica de negocio necesita un componente del lado del servidor. Ya sea rutas de API Next.js, Funciones Edge de Supabase, o un servicio backend separado — algo necesita validar operaciones donde el usuario no pueda manipularlas.

Esta es exactamente la razón por la que a menudo recomendamos marcos como Next.js o Astro para aplicaciones SaaS de producción — te dan renderizado del lado del servidor y rutas de API por defecto.

Funciones Edge de Supabase: Qué Falta

Algunos proyectos de Lovable sí usan Funciones Edge de Supabase para ciertas operaciones — típicamente manejo de webhooks de Stripe o envío de correos. Pero la implementación a menudo tiene problemas:

  1. Sin validación de entrada: Las Funciones Edge aceptan y procesan cualquier JSON que se les envíe sin validar forma, tipos o restricciones.

  2. CORS configurado para permitir todos los orígenes:

// Patrón común en Funciones Edge de Lovable
const corsHeaders = {
  'Access-Control-Allow-Origin': '*',  // Permite que cualquier sitio web llame esto
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}
  1. Sin verificación de autenticación: La función no verifica el token JWT, por lo que usuarios no autenticados pueden llamarla.

  2. Las firmas de webhooks de Stripe no se verifican: En dos proyectos, el controlador de webhook de Stripe no verificaba la firma del webhook, lo que significa que cualquiera podría enviar eventos de pago falsos al punto final.

// Lo que encontramos — sin verificación de firma
Deno.serve(async (req) => {
  const body = await req.json()
  // Procesa directamente el evento sin verificar que vino de Stripe
  if (body.type === 'checkout.session.completed') {
    // Actualiza la suscripción del usuario
    await supabaseAdmin.from('subscriptions').update({
      status: 'active',
      plan: 'pro'
    }).eq('user_id', body.data.object.metadata.user_id)
  }
})

Esto significa que un atacante podría enviar una solicitud POST al URL del webhook con un evento checkout.session.completed falso y actualizar a cualquier usuario a un plan pro gratis.

Patrones de Vulnerabilidad Comunes que Encontramos

Aquí hay un resumen de los problemas más comunes clasificados por severidad y frecuencia:

Vulnerabilidad Severidad Frecuencia (de 6) Explotabilidad
RLS faltante en tablas sensibles Crítica 6/6 Fácil — simplemente consulta la tabla
Políticas RLS demasiado permisivas Alta 6/6 Fácil con clave anon
Exposición de clave service_role Crítica 3/6 Trivial si se encuentra
Sin verificación de webhook de Stripe Alta 4/6 Media — necesita URL del endpoint
Autorización solo del lado del cliente Alta 6/6 Fácil con DevTools
Sin validación de entrada en Funciones Edge Media 5/6 Media
CORS con comodín en Funciones Edge Media 5/6 Fácil
Datos sensibles en localStorage Media 4/6 Acceso físico o XSS
Sin limitador de velocidad Media 6/6 Trivial
Referencias directas a objetos inseguros Alta 5/6 Fácil — cambia el ID en la URL

Cómo Auditar tu Propio Proyecto Lovable

Si has construido algo con Lovable que maneje datos reales de usuarios, aquí se explica cómo buscar estos problemas tú mismo.

Paso 1: Verifica tu Estado de RLS de Supabase

Ve a tu panel de Supabase → Editor de Tablas. Haz clic en cada tabla y verifica si RLS está habilitado. Luego ve a Autenticación → Políticas y revisa cada política.

O ejecuta esta consulta en el Editor SQL:

SELECT
  schemaname,
  tablename,
  rowsecurity
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY tablename;

Si rowsecurity es false para cualquier tabla que contenga datos de usuario, ese es un problema crítico.

Paso 2: Busca Claves Expuestas

En tu código, busca:

grep -r "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" src/
grep -r "service_role" src/
grep -r "SUPABASE_SERVICE" src/

El primer patrón coincide con el comienzo de las claves JWT de Supabase. Si encuentras la clave service_role en cualquier lugar en tu directorio src/, esa es una vulnerabilidad crítica inmediata.

Paso 3: Prueba Políticas RLS

Crea una segunda cuenta de usuario de prueba. Inicia sesión como ese usuario e intenta acceder a datos del usuario uno. Verifica la pestaña Network del navegador — ¿estás recibiendo datos que no deberías?

También puedes probar directamente con curl:

curl 'https://TU_PROYECTO.supabase.co/rest/v1/user_profiles?select=*' \
  -H "apikey: TU_CLAVE_ANON" \
  -H "Authorization: Bearer TU_CLAVE_ANON"

Si esto devuelve todos los perfiles de usuario sin autenticación, RLS está roto.

Paso 4: Verifica Funciones Edge

Revisa cada Función Edge para:

  • Verificación de JWT
  • Validación de entrada
  • Configuración de CORS
  • Verificación de firma de webhook (para controladores de Stripe/pagos)

Paso 5: Inspecciona el Paquete del Lado del Cliente

Ejecuta npm run build e inspecciona la salida. Busca en el JavaScript compilado claves de API, lógica de negocio y datos de precios. Cualquier cosa en el paquete es visible para los usuarios.

Cuándo Reconstruir vs. Cuándo Remediar

Esta es la pregunta que cada fundador de Lovable enfrenta una vez que se da cuenta de que estos problemas existen. La respuesta depende de varios factores:

Remedia si:

  • Tu aplicación tiene menos de 10 tablas
  • No tienes un modelo de autorización complejo (sin multiinquilino, sin roles)
  • La arquitectura central (modelo de datos, estructura de página) es sólida
  • Principalmente necesitas agregar políticas RLS y mover algo de lógica al servidor

Reconstruye si:

  • Necesitas arquitectura multiinquilino con roles y permisos
  • Tu lógica de negocio es compleja y completamente del lado del cliente
  • Necesitas renderizado del lado del servidor para SEO o rendimiento
  • El esquema de Supabase tiene problemas estructurales significativos
  • Estás a una escala donde necesitas infraestructura adecuada

Para remediación, típicamente estás mirando agregar políticas RLS en todas las tablas, migrar lógica sensible a Funciones Edge o una capa del lado del servidor, implementar validación de entrada adecuada, y agregar limitación de velocidad. Este es un proyecto de 2-4 semanas para un desarrollador experimentado dependiendo de la complejidad.

Para una reconstrucción completa, típicamente recomendamos una arquitectura sin cabeza con separación adecuada de preocupaciones. Cuesta más al principio pero te da una base que escala. Consulta nuestra página de precios para una idea de cómo se ve eso.

Si no estás seguro de cuál es el camino correcto, estamos felices de hacer una evaluación rápida. Contáctanos en nuestra página de contacto.

Preguntas Frecuentes

¿Es seguro usar Lovable para aplicaciones de producción? Lovable puede generar un buen punto de partida, pero la salida necesita un endurecimiento de seguridad significativo antes de que esté lista para producción. El código generado carece de políticas RLS adecuadas, validación del lado del servidor y lógica de autorización. Piénsalo como andamiaje, no como el edificio terminado. Absolutamente necesitas un desarrollador para revisar y asegurar el código antes de que usuarios reales confíen sus datos a él.

¿Lovable expone mis claves API de Supabase? La clave anon de Supabase es intencionalmente pública — eso es por diseño, y el modelo de seguridad de Supabase lo tiene en cuenta a través de RLS. El problema es cuando Lovable (o tú, a través de indicaciones) coloca la clave service_role en código del lado del cliente. Que la clave anon sea pública es solo segura si tus políticas RLS son impecables, lo que en proyectos generados por Lovable, típicamente no son.

¿Qué es Row Level Security y por qué importa? Row Level Security (RLS) es una característica de PostgreSQL que Supabase usa para controlar qué filas un usuario puede leer, insertar, actualizar o eliminar. Sin RLS, cualquiera con tu clave anon pública puede consultar tu base de datos completa — los datos de cada usuario, cada registro privado. Es el mecanismo de seguridad más importante en una aplicación respaldada por Supabase, y es lo más comúnmente mal configurado en proyectos de Lovable.

¿Puedo arreglar problemas de seguridad de Lovable yo mismo sin un desarrollador? Si entiendes SQL y la sintaxis de política RLS de Supabase, puedes agregar políticas RLS básicas tú mismo usando el panel de Supabase. Sin embargo, obtener las políticas correctas — especialmente para escenarios complejos como multiinquilino, recursos compartidos, o acceso de administrador — requiere experiencia. Una política incorrecta puede bloquear a los usuarios de sus propios datos o dejar todo expuesto. Para cualquier cosa más allá de un proyecto personal simple, obtén ojos profesionales en ello.

¿Cómo verifico si la base de datos de mi aplicación Lovable es segura? La prueba más rápida: abre DevTools en tu navegador, ve a la pestaña Network, y mira las llamadas a API de Supabase que hace tu aplicación. Copia el valor del encabezado apikey. Luego usa curl o Postman para consultar tus tablas directamente usando solo esa clave sin token de auth. Si recuperas datos de otros usuarios — o cualquier dato en absoluto en tablas que deberían ser privadas — tu RLS está roto.

¿Cuáles son los mayores riesgos de seguridad con código generado por IA en general? Los generadores de código IA optimizan para hacer que las cosas funcionen, no para hacerlas seguras. No tienen un modelo mental de tu panorama de amenazas. Los mayores riesgos son: secretos expuestos, validación de entrada faltante, controles de acceso demasiado permisivos, y la ausencia de límites de seguridad del lado del servidor. Estos no son únicos de Lovable — problemas similares existen en código de Cursor, v0, Bolt y otras herramientas de IA. La diferencia es que Lovable genera aplicaciones completas que la gente implementa directamente en producción.

¿Debería cambiar de Supabase a un backend diferente después de usar Lovable? Supabase en sí está bien. Es una plataforma sólida con capacidades de seguridad adecuadas. El problema es cómo Lovable la configura. No necesitas abandonar Supabase — necesitas configurar adecuadamente las políticas RLS, mover operaciones sensibles a Funciones Edge, y agregar la capa de autorización que Lovable omitió. La infraestructura es buena; la configuración simplemente necesita trabajo.

¿Cuánto cuesta arreglar problemas de seguridad en una aplicación generada por Lovable? Para una remediación directa — agregar políticas RLS, asegurar Funciones Edge, eliminar claves expuestas, agregar validación de entrada básica — estás mirando aproximadamente £3,000-£8,000 dependiendo del número de tablas y complejidad de tu modelo de autorización. Una reconstrucción completa con arquitectura adecuada corre £15,000-£50,000+ dependiendo del alcance. El camino de remediación es casi siempre más rentable si tu modelo de datos central es sólido.


¿Atrapado en un rescate de Lovable?

Rescatamos aplicaciones Lovable rotas — desconfiguración de RLS, claves API expuestas, bucles de bugs infinitos, límites de escalado. Sprints de rescate de alcance fijo comenzando en GBP 5K / USD 6.5K. Ver el servicio de Rescate de Aplicaciones Lovable →