AI-coded apps

    Vulnerabilidad IA: Cómo Agregar Row Level Security a tu App en Lovable

    El editor de políticas de Supabase mostrando Row Level Security activado en una app de Lovable.

    Para añadir Row Level Security a tu app en Lovable, activa RLS en cada tabla de tu proyecto Supabase y escribe políticas que limiten a cada usuario a sus propias filas. Es imprescindible porque Supabase crea las tablas con RLS desactivado, así que sin este paso cualquiera con tu clave anon pública puede consultar y volcar toda la base de datos, exactamente el fallo detrás de CVE-2025-48757. Puedes hacerlo desde el panel de Supabase o pidiéndoselo a la IA de Lovable, y luego debes verificarlo consultando con la clave anon.

    Respuesta rápida

    Añadir RLS son dos pasos: activarlo en cada tabla y escribir políticas. Según la documentación de Supabase, las tablas se crean con RLS desactivado, así que hay que activarlo en todas. Luego escribe una política por operación, para leer, crear, editar y borrar, que use auth.uid() para que cada usuario acceda solo a sus filas. La clave anon es pública por diseño, según la documentación de claves, y es segura solo cuando RLS la gobierna. Sin RLS, un atacante la usa para volcar tus tablas, el fallo de CVE-2025-48757. Verifica consultando con la clave anon sin sesión.

    Por qué tu app de Lovable necesita RLS

    Row Level Security es la capa que hace segura una app de Supabase, y es justo la que las herramientas de IA suelen omitir. Supabase crea las tablas con RLS desactivado por defecto, de modo que si tu proyecto de Lovable nunca lo activa, la clave anon pública, que viaja en el cliente, puede consultar cualquier tabla y descargarla entera: listas de usuarios, registros de pago u otros datos sensibles, sin iniciar sesión.

    Esto no es teórico. En CVE-2025-48757, un investigador encontró 170 proyectos de Lovable cuyas tablas eran legibles por peticiones no autenticadas usando solo la clave anon, porque faltaba RLS. La clave anon no se había filtrado, es pública a propósito; el problema era que nada protegía los datos detrás de ella. Añadir RLS es lo que cierra esa puerta.

    Paso 1: activa RLS en cada tabla

    El primer paso es activar Row Level Security en todas las tablas, sin excepción. En el panel de Supabase, abre el editor de tablas, selecciona cada tabla y activa RLS; también puedes hacerlo con SQL mediante ALTER TABLE nombre_tabla ENABLE ROW LEVEL SECURITY. Una tabla sin RLS queda completamente abierta a la clave anon, así que ninguna puede quedarse fuera.

    Ten en cuenta un efecto importante: al activar RLS sin ninguna política, la tabla queda cerrada por completo, es decir, nadie puede leer ni escribir hasta que crees políticas. Eso es lo correcto por defecto, y el siguiente paso es abrir el acceso justo a lo necesario mediante políticas, en lugar de dejar la tabla abierta a todo el mundo.

    Paso 2: escribe políticas para cada operación

    Con RLS activo, defines qué puede hacer cada usuario mediante políticas, y conviene una por operación. En Postgres, las operaciones son SELECT para leer, INSERT para crear, UPDATE para editar y DELETE para borrar, y cada una puede tener su propia política. La tabla siguiente resume el patrón habitual.

    OperaciónPolítica típicaCon qué se comprueba
    SELECT (leer)El usuario lee solo sus filasauth.uid() = user_id
    INSERT (crear)El usuario crea filas como suyasauth.uid() = user_id (WITH CHECK)
    UPDATE (editar)El usuario edita solo sus filasauth.uid() = user_id (USING y WITH CHECK)
    DELETE (borrar)El usuario borra solo sus filasauth.uid() = user_id (USING)

    La idea es abrir solo lo que cada usuario necesita. En lugar de una regla que permita todo, escribes reglas concretas que comparan la identidad del usuario con la fila, de modo que cada persona accede únicamente a lo suyo. Sin una política para una operación, esa operación queda denegada, que es el comportamiento seguro.

    La política más común: cada usuario ve solo sus filas

    La política que necesita casi cualquier app es sencilla: cada usuario accede solo a las filas que le pertenecen. Para lograrlo, tus tablas deben tener una columna que identifique al propietario, por ejemplo user_id, y la política compara esa columna con la identidad del usuario autenticado, disponible en Supabase como auth.uid().

    Una política de lectura típica permite SELECT cuando auth.uid() coincide con el user_id de la fila. Repites la idea para crear, editar y borrar, usando USING para lo que el usuario puede ver o afectar y WITH CHECK para lo que puede escribir. Con estas cuatro políticas, un usuario no puede leer ni tocar los datos de otro, aunque comparta la misma clave anon pública.

    Hacerlo en Lovable o en el panel de Supabase

    Tienes dos caminos, y ambos funcionan porque Lovable se conecta a un proyecto real de Supabase. Puedes pedirle a la IA de Lovable que active RLS y escriba las políticas, describiendo qué debe poder hacer cada usuario; o puedes ir directamente al panel de Supabase y configurarlo tú, con el editor de políticas o con SQL.

    Cualquiera que sea el camino, la responsabilidad de verificar es tuya. La IA puede generar políticas incompletas o dejar una tabla sin cubrir, así que después de pedírselo revisa en el panel de Supabase que RLS está activo en todas las tablas y que cada operación tiene su política. No des por hecho que "hecho por la IA" significa "hecho bien".

    Un detalle de rendimiento: (select auth.uid())

    Al escribir políticas hay un detalle que mejora el rendimiento. Llamar a auth.uid() directamente en una política hace que Postgres la evalúe fila por fila, lo que en tablas grandes ralentiza las consultas. Envolver la llamada como (select auth.uid()) permite a Postgres evaluarla una sola vez, lo que puede acelerar mucho las consultas sin cambiar la seguridad.

    Es un ajuste pequeño con un impacto real en tablas con muchas filas. La lógica de seguridad es idéntica, cada usuario sigue viendo solo lo suyo, pero la consulta es más eficiente. Si tu app crece, adoptar esta forma desde el principio te evita revisar todas las políticas más adelante.

    Verifica que RLS funciona

    Activar RLS y escribir políticas no basta; hay que comprobar que de verdad protege. La tabla siguiente da una lista di verifica clara.

    PasoAcciónConfirma
    1Activa RLS en cada tablaNinguna tabla queda abierta
    2Crea políticas para SELECT, INSERT, UPDATE, DELETECada operación está cubierta
    3Usa auth.uid() para limitar por usuarioCada uno ve solo lo suyo
    4Consulta con la clave anon sin sesiónNo devuelve datos ajenos
    5Prueba con dos usuarios distintosEl aislamiento funciona
    6Revisa que no haya service_role en el clienteNada omite RLS

    La comprobación más importante es la cuarta: consulta tus tablas con la clave anon pública, sin sesión iniciada, y confirma que no devuelve datos que no debería. Es exactamente la prueba que hace un atacante o un bot de rastreo, así que superarla tú mismo es la señal directa de que el fallo de CVE-2025-48757 no está en tu app.

    Errores comunes al añadir RLS

    Los errores al añadir RLS se repiten. El más grave es dejar una tabla sin activar RLS, que queda abierta aunque las demás estén protegidas. Otro es activar RLS pero olvidar una operación, por ejemplo cubrir la lectura y no la escritura. Y otro es escribir una política demasiado permisiva, del tipo "permitir a todos", que en la práctica anula la protección.

    Evitarlos es cuestión de método. Recorre todas las tablas, confirma que cada una tiene RLS activo y una política para cada operación que uses, y prueba con dos usuarios distintos para ver que el aislamiento funciona. Y nunca dejes la clave service_role en el cliente, porque omite RLS por completo y haría inútil todo el trabajo anterior.

    Antes de publicar, escanea la build

    RLS protege tu backend, pero tu app publicada también puede arrastrar problemas del lado del cliente que RLS no cubre: una clave incrustada, tráfico en claro o una configuración insegura. Como las herramientas de IA facilitan estos descuidos, revisar la build antes de publicar los detecta cuando aún son baratos de corregir.

    Un escáner como PTKD.com analiza tu .apk o .ipa y devuelve resultados ordenados por gravedad y alineados con OWASP MASVS, incluidos los secretos embebidos y las configuraciones de red inseguras. Con un límite claro: un escáner de la build revisa la app que publicas, no tu panel de Supabase, así que no sustituye a activar RLS ni a escribir políticas. Detecta la exposición del lado del cliente; el backend lo aseguras tú con RLS.

    Qué recordar

    • Supabase crea las tablas con RLS desactivado, así que actívalo en todas las tablas de tu app de Lovable.
    • Escribe una política por operación, para leer, crear, editar y borrar, usando auth.uid() para limitar a cada usuario a sus filas.
    • Puedes hacerlo en Lovable o en el panel de Supabase, pero verifica tú mismo el resultado.
    • Comprueba consultando con la clave anon sin sesión que no expone datos ajenos, el fallo de CVE-2025-48757.
    • Antes de publicar, escanea la build con PTKD.com para los problemas del lado del cliente que RLS no cubre.
    • #lovable
    • #supabase
    • #row level security
    • #seguridad IA
    • #auth.uid

    Frequently asked questions

    ¿Qué es Row Level Security en Supabase?
    Es una función de Postgres que controla qué filas de una tabla puede ver o modificar cada usuario, mediante políticas. En Supabase, es la capa que hace segura la clave anon pública: con RLS activo y políticas correctas, esa clave solo accede a los datos que permites. Sin RLS, la clave anon puede leer toda la tabla.
    ¿Por qué mi app de Lovable no tiene RLS por defecto?
    Porque Supabase crea las tablas con RLS desactivado, y las herramientas de IA no siempre lo activan al generar el proyecto. La IA optimiza para que la app funcione, no para que sea segura, así que suele dejar las tablas abiertas. Activar RLS y escribir políticas es un paso que debes añadir tú.
    ¿Cómo activo RLS en una tabla?
    En el panel de Supabase, abre el editor de tablas, selecciona la tabla y activa Row Level Security; o usa SQL con ALTER TABLE nombre ENABLE ROW LEVEL SECURITY. Al activarlo sin políticas, la tabla queda cerrada por completo, y luego abres el acceso justo con políticas. Hazlo en todas las tablas, sin excepción.
    ¿Qué política necesito para que cada usuario vea solo sus datos?
    Necesitas una columna que identifique al propietario, como user_id, y una política que compare auth.uid() con esa columna. Una política de lectura permite SELECT cuando auth.uid() coincide con el user_id de la fila, y repites la idea para crear, editar y borrar. Así cada usuario accede solo a sus filas.
    ¿Puedo pedirle a Lovable que añada RLS?
    Sí. Puedes pedir a la IA de Lovable que active RLS y escriba las políticas, describiendo qué debe poder hacer cada usuario. Pero verifica el resultado en el panel de Supabase, porque la IA puede dejar una tabla sin cubrir o generar una política incompleta. La comprobación final es responsabilidad tuya.
    ¿Cómo compruebo mi app antes de publicar?
    Verifica RLS consultando tus tablas con la clave anon sin sesión y confirmando que no expone datos ajenos. Para el lado del cliente, un escáner como PTKD.com (https://ptkd.com) revisa tu build en busca de secretos embebidos y configuraciones inseguras, alineado con OWASP MASVS. Revisa el backend con RLS y el cliente con el escáner.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free