AI-coded apps

    Los Bots Ya Buscan las Contraseñas Supabase Expuestas Por Desarrollos Cursor JS

    Un bot rastreando una clave service_role de Supabase incrustada en el bundle JavaScript de una app generada por IA.

    Sí, los bots ya rastrean de forma automática las claves de Supabase expuestas en el código JavaScript que generan asistentes de IA como Cursor. Lo importante es saber qué clave se expuso: la clave anon (publishable) es pública por diseño, así que su exposición solo es peligrosa si no tienes Row Level Security; la clave service_role (secreta) nunca debe estar en el cliente, porque ignora RLS y da acceso total a tu base de datos. La IA a veces incrusta o commitea estas claves sin avisar. La defensa es revisar el código, mantener la clave secreta en el backend y activar RLS.

    Respuesta rápida

    La clave anon está pensada para ser pública; la clave service_role no lo está nunca. Según la documentación de claves de Supabase, la clave service_role ignora Row Level Security y tiene acceso completo, así que una fuga es una brecha crítica: rótala y muévela a un backend. Una clave anon expuesta solo es peligrosa si RLS está desactivado. Los asistentes de IA como Cursor generan JavaScript que a veces incrusta la clave en el bundle o la sube a Git, y los bots la encuentran en minutos: el informe State of Secrets Sprawl de GitGuardian contó 28,65 millones de secretos en repos públicos en 2025. Revisa el código, activa RLS y no confíes secretos al cliente.

    Por qué el código generado por IA filtra claves Supabase

    Los asistentes de IA optimizan para que el código funcione, no para que sea seguro, y por eso filtran claves con facilidad. Al pedirle a Cursor o a otro generador que conecte tu app con Supabase, suele producir código que pone la clave directamente en el frontend para que funcione a la primera, sin distinguir entre una clave pública y una secreta. Si esa clave es la service_role, el problema es grave.

    Además, la IA no gestiona tu higiene de secretos. Puede crear un archivo con la clave en claro, sugerir subirla al repositorio, o generar un proyecto sin activar RLS, porque su objetivo es que la app compile, no protegerte. La responsabilidad de revisar qué clave se usa y dónde acaba sigue siendo tuya.

    Clave anon vs service_role: cuál importa

    No todas las claves son iguales, y la primera pregunta es cuál se expuso. La clave anon es de bajo privilegio y está diseñada para viajar en el cliente; su seguridad depende de RLS. La clave service_role es una clave de administrador que ignora RLS y da acceso total. El secreto JWT firma los tokens. La tabla lo resume.

    Clave¿Segura en el cliente?Si se expone
    anon / publishableSí, por diseñoSegura solo si RLS está activo
    service_role / secretaNo, nuncaAcceso total a la base de datos; rotar ya
    Secreto JWTNo, nuncaPermite falsificar tokens de sesión

    Si se expuso la clave anon, no te alarmes por la clave en sí: la pregunta es si RLS protege tus datos. Si se expuso la service_role o el secreto JWT, es una emergencia, porque dan un control que ninguna política de RLS puede frenar.

    Cómo los bots encuentran y explotan las claves

    No es un ataque manual: es automático y constante. Los bots rastrean repositorios públicos de GitHub, bundles de JavaScript desplegados y binarios en busca de URLs y claves de Supabase, que siguen patrones reconocibles. Al encontrar una service_role, la prueban contra la API REST y obtienen acceso total en segundos. Al encontrar una anon, consultan tus tablas para ver si RLS está activo.

    La velocidad es el problema. Como el rastreo es continuo, una clave subida a un repo público o incluida en un bundle puede detectarse y probarse en minutos, mucho antes de que te des cuenta. Supabase ahora revoca de forma automática las claves secretas que detecta en repos públicos de GitHub, lo cual ayuda, pero no puedes confiar en descubrirlo después: la ventana de exposición basta.

    El paso que la IA suele saltarse: RLS

    Row Level Security es el control que hace segura una clave anon pública, y es justo el que la IA suele omitir. Supabase crea las tablas con RLS desactivado por defecto, así que si el código generado no lo activa ni escribe políticas, cualquiera con tu clave anon pública puede consultar tus tablas y volcarlas: listas de usuarios, registros de pago u otros secretos, sin iniciar sesión.

    Por eso RLS no es opcional. Actívalo en cada tabla y escribe políticas que coincidan con tu lógica de autenticación, por ejemplo que cada usuario solo lea sus propias filas. No dejes ninguna tabla accesible dando por hecho que la clave anon es secreta, porque no lo es. Este es exactamente el fallo que dejó expuestas apps generadas por IA a gran escala.

    Cómo revisar el código que genera Cursor

    Trata todo el código que genera la IA como un borrador que hay que auditar, no como algo listo para producir. Antes de commitear, busca claves incrustadas, comprueba qué clave de Supabase usa cada archivo, y confirma que la service_role no aparece en ningún fichero del frontend. Revisa también que el .gitignore excluye los archivos con secretos.

    Una precisión importante sobre los .env: en una app de frontend, las variables de entorno se integran en claro en el bundle al compilar, así que un .env organiza tus valores en desarrollo, pero no oculta una clave secreta en la app publicada. Un .env es útil para la clave anon pública, no para proteger la service_role, que debe vivir en el backend.

    Respuesta inmediata si una clave ya se filtró

    Si una clave secreta o service_role ya se expuso, actúa en orden. La tabla siguiente da una respuesta clara.

    PasoAcciónPrioridad
    1Rotar la clave service_role o secreta expuestaInmediata
    2Activar RLS en cada tablaAlta
    3Escribir políticas según tu lógica de autenticaciónAlta
    4Quitar la clave del bundle y del historial de GitAlta
    5Mover la service_role a un backendAlta
    6Consultar tus tablas con la clave anon para verificarContinua

    La acción más urgente es la primera: rotar la clave, porque es lo único que invalida la copia que un atacante ya pudo recoger. Borrar el commit no basta, porque el historial de Git conserva las versiones anteriores. Después, revisa los registros de tu base de datos por si hubo accesos anómalos.

    Buenas prácticas en un flujo con IA

    Trabajar con Cursor u otra IA es compatible con la seguridad si añades unos hábitos. Pide explícitamente que las claves sensibles no se pongan en el cliente, revisa cada bloque generado antes de aceptarlo, y mantén la service_role solo en funciones de servidor o Edge Functions. Activa el secret scanning y la protección de push de GitHub para atrapar los olvidos.

    La idea central es no delegar en la IA las decisiones de seguridad. La IA acelera el desarrollo, pero la arquitectura segura, con el cliente usando la clave anon y RLS, y las operaciones privilegiadas en el backend, sigue siendo decisión tuya. Un flujo con IA bien revisado es seguro; uno que acepta el código a ciegas, no.

    Los límites de fiarse de la IA

    Conviene ser honesto: la IA no sabe cuál de tus claves es secreta ni si tus políticas de RLS son correctas. Genera código que funciona, y funcionar incluye poner una clave donde no debe. Tampoco te avisa de que Supabase crea las tablas sin RLS. Esperar que la IA se encargue de tu seguridad es el error de fondo.

    Del mismo modo, ninguna herramienta única resuelve todo. La combinación correcta es revisión humana del código generado, RLS bien configurado en el backend, y un escaneo del build antes de publicar. Cada pieza cubre lo que las otras no ven.

    Escanear el build antes de publicar

    Como los generadores de IA facilitan cometer estos fallos, revisar el build antes de que salga los atrapa cuando aún son baratos de corregir. Una clave service_role commiteada, una política de RLS ausente o un secreto en el bundle son justo los patrones que buscan los atacantes automáticos.

    Un escáner como PTKD.com analiza tu build móvil y devuelve resultados ordenados por gravedad y alineados con OWASP MASVS, incluidos los secretos embebidos y las configuraciones de red y almacenamiento inseguras, para que una clave expuesta no llegue a los usuarios. Con un límite claro: un escáner del build revisa la app que publicas, no tu panel de Supabase, así que no sustituye a activar RLS ni a rotar una clave en el servidor. Detecta la exposición del lado del cliente; el backend lo arreglas tú.

    Qué recordar

    • Los bots ya rastrean claves Supabase en el código JS generado por IA; la clave que se expuso decide la respuesta.
    • La clave anon es pública por diseño y solo es peligrosa sin RLS; la service_role nunca debe estar en el cliente.
    • La IA optimiza para que funcione, no para que sea seguro, así que revisa cada clave y activa RLS tú mismo.
    • Un .env no oculta secretos en el frontend; la service_role debe vivir en el backend.
    • Escanea cada build con PTKD.com para que una clave commiteada no llegue a producción.
    • #supabase
    • #cursor
    • #seguridad IA
    • #row level security
    • #clave service_role

    Frequently asked questions

    ¿La clave anon de Supabase es segura si se expone?
    Sí, por diseño, siempre que Row Level Security esté activo con políticas correctas. La clave anon es de bajo privilegio y está pensada para el cliente; RLS limita lo que puede acceder. Sin RLS, esa misma clave pública permite a cualquiera consultar tus tablas, lo cual es peligroso, pero es un problema de política ausente, no de clave filtrada.
    ¿Qué pasa si mi clave service_role se filtra?
    Es una brecha crítica. La clave service_role ignora RLS y tiene acceso total de lectura y escritura, así que cualquiera con ella puede volcar, modificar o borrar todos tus datos. Rótala de inmediato, quítala del cliente y del historial de Git, muévela a un backend y revisa tus registros por si se usó.
    ¿Por qué el código de Cursor o de una IA filtra claves?
    Porque la IA optimiza para que el código funcione, no para que sea seguro. Suele poner la clave directamente en el frontend para que la app conecte a la primera, sin distinguir entre una clave pública y una secreta, y puede sugerir subirla al repositorio o generar el proyecto sin activar RLS. La revisión sigue siendo tuya.
    ¿Cómo evito que la IA incruste secretos?
    Pide explícitamente que las claves sensibles no se pongan en el cliente, revisa cada bloque antes de aceptarlo, y mantén la service_role solo en el backend o en Edge Functions. Activa el secret scanning y la protección de push de GitHub, y comprueba el .gitignore para no subir archivos con secretos.
    ¿Sirve un .env para ocultar la clave en el frontend?
    No para una clave secreta. En una app de frontend, las variables de entorno se integran en claro en el bundle al compilar, así que un .env organiza tus valores en desarrollo pero no los oculta en la app publicada. Sirve para la clave anon pública; la service_role debe vivir en el backend.
    ¿Cómo compruebo mi build antes de publicar?
    Analiza el build antes de cada publicación. Un escáner como PTKD.com (https://ptkd.com) inspecciona tu .ipa o .apk y señala secretos embebidos y configuraciones de red y almacenamiento inseguras, alineados con OWASP MASVS. No sustituye a activar RLS ni a rotar una clave en el servidor, pero evita que una clave del lado del cliente llegue a los usuarios.

    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