¿Es segura tu app de Cursor?
¿Es seguro hacer apps de producción con Cursor? El código suele funcionar bien. Funcionar y estar protegido son pruebas distintas, y solo una se ejecuta.

Los logotipos son propiedad de sus respectivos dueños y se muestran solo para indicar compatibilidad.
En resumen
- Una app hecha con Cursor suele ser segura de ejecutar. Si es segura de exponer es otra prueba, y nadie la ejecuta por ti.
- El código generado responde a la pregunta que hiciste. Qué filas puede ver un visitante es una pregunta que pertenece a la base de datos.
- La forma habitual de publicar una clave secreta: un refactor del servidor al navegador y luego añadir NEXT_PUBLIC_ o VITE_ para que el error desaparezca.
Cursor te da control de verdad (tu repositorio, tus archivos, tu despliegue), y eso cambia dónde está el riesgo. No estás preguntándote qué hizo un builder en tu nombre. Estás revisando mucho código que funciona, deprisa, y decidiendo qué te lees a fondo.
Aquí está lo que guía tras guía cuenta mal: preguntar si la IA escribe código inseguro es la pregunta equivocada. El código generado se escribe para satisfacer lo que pediste. «Carga los pedidos del usuario» lo satisface un código que carga pedidos. En esa frase no dice de quién, así que la respuesta tampoco lo decide, y el lugar al que pertenece esa decisión no es el archivo que estás revisando.
Funcionar y estar protegido son dos pruebas distintas
Solo una se ejecuta sola.
Piénsalo como una tienda. Tu app es el escaparate: cada página que construyes se le entrega entera a cada visitante, porque un navegador no puede pintar lo que no le enviaron. Tu base de datos es el almacén, un edificio aparte en internet con su propia cerradura y su propia dirección.
Cuando ejecutas tu app y funciona, has probado el escaparate: para ti aparecen las cosas correctas en las pantallas correctas. No has probado la cerradura. Al almacén se llega directamente, sin pasar por tu tienda, y que tu app cargue bien no dice nada sobre qué le devuelve a alguien que se salta la puerta principal.
Esa es la prueba que nunca se ejecuta sola, en ningún proyecto, generado o escrito a mano. Es más fácil saltársela cuando el código llega más rápido de lo que puedes leerlo.
Dónde se tuercen las claves en un proyecto de Cursor
En el paso del servidor al navegador, casi siempre.
Hay dos tipos de credencial y se parecen casi por completo. Una clave
publicable nombra tu proyecto y nada más (sb_publishable_… en los proyectos
nuevos de Supabase, anon en los antiguos), y está diseñada para vivir en un
navegador. Una clave secreta, sb_secret_… o la antigua service_role,
ignora todas las reglas que hayas escrito y puede leer y escribir cada fila que
tengas.
La secuencia que publica una es de lo más común. Código que usaba una clave
secreta en el servidor se refactoriza a un componente que se ejecuta en el
navegador. El valor vuelve como undefined, así que se renombra la variable con
el prefijo que quiera la herramienta de compilación (NEXT_PUBLIC_ en Next.js,
VITE_ en Vite), y la app empieza a funcionar. La propia documentación de Vite es
tajante sobre lo que hace ese prefijo: esos valores se empaquetan en tu código
fuente al compilar.
.gitignore no ayuda aquí. Gobierna lo que se sube al repositorio, y la salida
de tu compilación se genera después. Si prefieres asegurarte de cuál de tus claves es cuál,
hay una comprobación de un minuto.
La comprobación que pertenece a la base de datos
Row Level Security, si tus datos están en Supabase: un interruptor por tabla que decide fila a fila quién puede leer qué.
Esta es la respuesta al problema de «carga los pedidos». En vez de confiar en que cada consulta del código filtre correctamente, la base de datos se niega a devolver filas a las que el visitante no tiene derecho, dijera lo que dijera la consulta y la escribiera quien la escribiera. Una regla, aplicada en el único sitio por el que toda petición tiene que pasar.
Dos detalles deciden si la tienes. Supabase activa Row Level Security por defecto en las tablas creadas en el Table Editor del panel, y no en las creadas ejecutando SQL, que es como las crea un archivo de migración. Y el ajuste solo enciende la comprobación; quién pasa lo decide la política que hay detrás, y una política puede permitir a todo el mundo igualmente.
Cómo revisar tu propio proyecto de Cursor en unos diez minutos
Busca en tu salida de compilación, no en el código fuente. Compila la app y
luego busca en los archivos generados service_role, sb_secret_ y sk_live_.
Todo lo que aparezca está publicado. Es más rápido y más honesto que leer el
fuente, porque es lo que reciben los visitantes de verdad.
Lee tu archivo de entorno buscando prefijos. Toda variable NEXT_PUBLIC_ o
VITE_ es pública por diseño. Para cada una, pregúntate si la imprimirías en tu
página de inicio.
Abre Authentication → Policies en Supabase. Cualquier tabla que muestre Row Level Security como desactivado la puede leer quien tenga la dirección de tu proyecto, que está dentro de tu app.
Y luego mira desde fuera. Nuestro escaneo gratuito hace ese último paso por ti: lee tu web en vivo como un visitante y te da una nota en unos 20 segundos, sin cuenta: escanea tu app.
Qué hacer
- Una app que funciona ha pasado una prueba. Si la base de datos rechaza a un desconocido es otra prueba que nadie ejecuta por ti.
- El código generado responde a la pregunta que hiciste. «Qué filas puede ver esta persona» es una pregunta que pertenece a la base de datos.
- La forma común de publicar una clave secreta es un refactor del servidor al navegador seguido de un cambio de prefijo.
.gitignoreprotege tu repositorio, no la salida de tu compilación.- En Supabase, las tablas creadas ejecutando SQL empiezan sin Row Level Security, y activarlo deja todas las filas legibles hasta que una política diga otra cosa.
Compila tu proyecto y busca service_role y sk_live_ en la salida antes que
nada; lleva un minuto y la respuesta no admite dudas. Después, la
lista de seguridad en 10 minutos es la ruta más corta por el resto.
Qué puede salir mal de verdad con una app creada con Cursor
Nada de esto significa que hayas hecho algo mal: son los efectos secundarios normales de dejar que la IA escriba código rápido. Esto es lo que vale la pena comprobar:
Una clave secreta escrita directamente en el código
Cuando la IA conecta un servicio, a veces pone la clave directamente en el código para que funcione, y si ese código se ejecuta en el navegador, cualquiera puede leerla. Algunas claves se supone que deben ser públicas y eso está bien; Reeve lee el código cargado de tu app, encuentra todas las claves y te dice cuáles son seguras y cuáles deben moverse al servidor.
Un .env commiteado o una carpeta .git expuesta
Las claves se supone que viven en un archivo .env que nunca se publica. Pero es fácil commitear .env por accidente, o desplegar la carpeta oculta .git, de modo que todo el historial, claves incluidas, queda descargable. Reeve comprueba si cualquiera de los dos es accesible desde fuera.
Tu base de datos abierta (RLS desactivado)
Si tu app guarda datos (a menudo en Supabase u otro Postgres), hay una regla (Row Level Security) sobre quién puede leer o cambiar cada fila. Si está desactivada, tus tablas pueden estar abiertas para cualquiera que encuentre la dirección. Es el problema serio más común, e invisible a menos que lo compruebes.
Almacenamiento de archivos público
Si tu app acepta subidas, estas viven en «buckets» de almacenamiento. Un bucket público significa que cualquiera puede listar o descargar lo que hay dentro, así que un archivo privado puede acabar visible para todos. Reeve comprueba si tus buckets son listables; nunca descarga los archivos de nadie.
Source maps dejados activos
Un «source map» revela el código original de tu app a cualquiera que mire. Útil mientras construyes, pero en producción da a extraños una copia legible de cómo funciona tu app y hace más fáciles de encontrar otras brechas. Conviene ordenarlo. Reeve comprueba si los tuyos están expuestos.
Cabeceras de seguridad ausentes y endpoints abiertos
Pequeños ajustes que le dicen a los navegadores cómo proteger a tus visitantes, más si tus endpoints de datos responden a cualquiera o a cualquier sitio. Menores por sí solos; juntos suman. Reeve señala lo que falta.
Qué es Reeve, y qué no
Reeve es una comprobación gratuita, de solo lectura y desde fuera, como un inspector que prueba las puertas sin entrar. Es rápida y detecta los errores comunes de alto impacto. No es una auditoría de seguridad completa, y una nota limpia no es garantía. Significa que las puertas obvias están cerradas.
Cursor es un editor, no un hosting, así que no despliega ni vigila tu app por ti; más de eso recae en ti y en el código que la IA produjo. Las propias herramientas de Cursor pueden ayudar a revisar el código sobre la marcha, y si usas Supabase su asesor señala problemas de base de datos. Lo que Reeve añade: una vista desde fuera de la app que realmente publicaste, en palabras sencillas con las que puedes actuar. Y si prefieres no pensar en ello, podemos vigilarla por ti.
¿Quieres que se gestione, no solo que se compruebe?
Reeve Care sigue vigilando tu app, respalda tus datos y te ayuda a arreglar cosas cuando se rompen, para que puedas seguir creando en vez de preocuparte.
Conoce Reeve CarePreguntas frecuentes
¿Es seguro el código escrito por la IA de Cursor?
Puede ser buen código, pero «escrito por IA» no significa «comprobado en seguridad». La IA optimiza para que las cosas funcionen, lo que a veces significa una clave en el lugar equivocado o una regla de base de datos ausente. La única forma de saberlo es comprobar qué está expuesto. Reeve lo hace gratis en unos 20 segundos.
Creo que commiteé un archivo .env. ¿Es peligroso?
Puede serlo, si el archivo (o la carpeta oculta .git) es accesible en tu sitio desplegado, porque puede contener claves activas. Reeve comprueba desde fuera si cualquiera de los dos es descargable, para que sepas si debes rotar esas claves.
¿Cómo sé si mi app de Cursor está filtrando claves de API?
La causa habitual es una clave escrita directamente en código que se ejecuta en el navegador. Reeve lee el código cargado de tu app, encuentra todas las claves y te dice cuáles son seguras de hacer públicas y cuáles deben moverse al servidor, sin guardar los valores reales.
¿Analizar mi app cambiará algo?
No. Reeve solo mira lo que ya es público desde fuera. Nunca inicia sesión, nunca cambia nada y nunca descarga tus archivos. Solo lectura, como comprobar si una puerta está cerrada sin entrar.
¿Cursor escribe código inseguro?
Esa es la pregunta equivocada para cualquier asistente, incluido uno humano. El código generado se escribe para satisfacer lo que pediste, y «haz que esta página cargue los pedidos» lo satisface un código que carga todos los pedidos. En la petición no decía cuáles, así que la respuesta tampoco lo decide. Da igual cómo formules la petición, la regla sobre quién puede leer qué filas tiene que vivir en la base de datos.
Mi archivo .env está en .gitignore. ¿Estoy cubierto?
Para tu repositorio, en gran parte. Pero .gitignore no tiene ningún efecto sobre lo que publica tu herramienta de compilación. Una variable con prefijo para el navegador (NEXT_PUBLIC_ en Next.js, VITE_ en Vite) se compila dentro del JavaScript que descargan tus visitantes, se guardara donde se guardara, y sigue en tu historial de versiones si el archivo se subió alguna vez antes de añadir la regla.
¿Cómo compruebo qué expone mi app de verdad, en vez de leer el código?
Carga tu propia web, abre las DevTools del navegador y mira la pestaña Red mientras se carga la página. Todo lo que aparece ahí es lo que recibe un visitante. Leerlo así lleva unos minutos y te dice más que leer el código fuente, porque es la misma vista que tiene alguien de fuera.