¿Es segura tu app de v0?
¿Es seguro construir con v0? Los componentes generados no son el riesgo. Lo es el cableado que añades alrededor, y un nombre de variable decide casi todo.

Los logotipos son propiedad de sus respectivos dueños y se muestran solo para indicar compatibilidad.
En resumen
- Una app de v0 suele poder publicarse sin miedo; los componentes generados no son el riesgo. Lo es el cableado que añades alrededor.
- Cualquier variable llamada NEXT_PUBLIC_… se compila dentro del JavaScript que descargan tus visitantes. Eso es correcto para una clave publicable y falso para una secreta.
- v0 no define las reglas de tu base de datos. En Supabase, las tablas creadas ejecutando SQL empiezan sin Row Level Security.
v0 te da componentes: una interfaz que funciona, generada y colocada en tu proyecto. Lo que no te da es el cableado de detrás: las variables de entorno, la base de datos, las reglas sobre quién puede leer qué. En ese hueco es donde un proyecto de v0 suele torcerse, y se tuerce en silencio.
Aquí está lo que guía tras guía cuenta mal: el código generado no es el riesgo. El riesgo es una convención de nombres en tu archivo de entorno y un ajuste de base de datos que no tiene nada que ver con v0.
Qué mitad de un proyecto de v0 es pública
La mitad de la interfaz, entera.
Piénsalo como una tienda. Los componentes que escribe v0 son el escaparate (cada página, cada formulario, cada botón), y el escaparate entero se le entrega a cada visitante que carga tu web. No hay forma de esquivarlo: un navegador no puede pintar una página que no le han enviado. Detrás está el almacén, tu base de datos, un edificio aparte con su propia cerradura.
Lo que distingue a un proyecto de v0 es que las dos mitades las ensamblas tú. Los componentes llegan sin saber nada de tus claves ni de tus tablas, así que cada decisión sobre qué cruza del almacén al escaparate la tomas tú en tu propio proyecto, normalmente en un único archivo lleno de variables de entorno.
Qué significa de verdad NEXT_PUBLIC_
Significa «pon esto en el navegador».
Next.js, que es para lo que genera v0, decide qué reciben tus visitantes leyendo
el nombre de la variable. Todo lo que se llame NEXT_PUBLIC_ALGO se compila
dentro del JavaScript que sirve tu web. Todo lo que no lleve ese prefijo se queda
en el servidor. La misma regla existe con otros nombres en otras herramientas
(Vite usa un prefijo VITE_ y dice claramente que esos valores se empaquetan en
tu código fuente al compilar), pero el efecto es idéntico: el prefijo publica el
valor.
Eso es exactamente lo correcto para una URL de proyecto o una clave publicable. Y exactamente lo contrario para una secreta.
La trampa tiene una forma reconocible. Algo de la interfaz no puede leer un
valor, así que se añade el prefijo para que el error desaparezca, y desaparece:
la app empieza a funcionar. Si el valor era una clave de Supabase
sb_publishable_…, o la antigua anon, no pasa nada. Si era sb_secret_… o
service_role, el error era el sistema diciéndote que ese código va en un
servidor, y el cambio de nombre publicó una clave que ignora todas las reglas que
hayas puesto.
Distinguir las dos lleva un
minuto y merece la pena hacerlo una vez por cada clave del archivo.
Qué decide si un desconocido puede leer tus datos
Las reglas de tu base de datos, no tus componentes.
Si tus datos están en Supabase, el ajuste es Row Level Security: un interruptor por tabla que decide fila a fila quién puede leer qué. Apagado, tu clave publicable devuelve la tabla entera a quien la pida. Encendido y con una política escrita, devuelve solo lo que la política permite.
Supabase lo activa por defecto en las tablas creadas en el Table Editor del panel, y no en las creadas ejecutando SQL. Así que las tablas que hiciste nacer haciendo clic suelen estar protegidas, y cualquier tabla creada por un archivo de migración puede que no. Después las dos se ven igual, y las dos funcionan.
Hay una segunda versión de esto que pilla a quien lo hizo todo bien: una tabla puede tener Row Level Security activado y seguir abierta a todo el mundo, por la política que lleva encima. Activado y protegido son dos estados distintos.
Cómo revisar tu propio proyecto de v0 en unos diez minutos
Lee tu archivo de entorno línea a línea. Toda variable con el prefijo
NEXT_PUBLIC_ está publicada. Pregúntate por cada una: ¿me quedaría tranquilo
imprimiendo esto en la página de inicio? Si no, no pertenece a ese prefijo.
Renueva cualquier cosa que nunca debió estar ahí. En el panel de tu proveedor, genera una clave nueva y revoca la antigua. Quitar la línea de tu código no cierra la puerta: el valor antiguo sigue en tu historial de versiones y en las copias en caché de la web.
Comprueba las reglas de tus tablas. En Supabase, Authentication → Policies lista cada tabla y si Row Level Security está encendido. Todo lo desactivado lo puede leer cualquiera que tenga la dirección de tu proyecto.
Y luego mira desde fuera. Los pasos de arriba te dicen qué está configurado; no te dicen qué se alcanza de verdad. Nuestro escaneo gratuito lee tu web en vivo como lo haría un visitante y te da una nota en unos 20 segundos, sin cuenta: escanea tu app.
Qué hacer
NEXT_PUBLIC_no es una formalidad. Compila el valor dentro de los archivos que descarga cada visitante.- Añadir el prefijo para callar un error es el momento de parar y comprobar qué contiene el valor en realidad.
- Una clave publicable pertenece al navegador.
sb_secret_…yservice_rolenunca. - v0 no define las reglas de tu base de datos. En Supabase, las tablas creadas ejecutando SQL empiezan sin Row Level Security.
- Una tabla con Row Level Security activado puede seguir abierta a todo el mundo. La política es la parte que decide.
Abre tu archivo de entorno y lee en voz alta las líneas NEXT_PUBLIC_. Si alguna
guarda algo que no imprimirías en tu página de inicio, renuévala ahora, y
después la lista de seguridad en 10 minutos cubre qué más conviene
desactivar en un proyecto recién lanzado.
Qué puede salir mal de verdad con una app de v0
Nada de esto es culpa tuya: son los efectos secundarios normales de generar código rápido. Esto es lo que vale la pena comprobar:
Una clave secreta en un componente cliente (la trampa NEXT_PUBLIC_)
v0 construye con Next.js, que tiene una regla que hace tropezar: cualquier cosa con nombre NEXT_PUBLIC_, y cualquier clave escrita directamente en un componente cliente, se envía al navegador, donde cualquiera puede leerla. Es fácil pegar una clave de API en un componente generado sin darte cuenta de que ahora es pública. Algunas claves se supone que deben ser públicas; Reeve las distingue de las que no, así que sin falsas alarmas.
Tu base de datos abierta (RLS de Supabase desactivado)
Si tu app de v0 guarda datos (a menudo en Supabase), hay un interruptor llamado Row Level Security (RLS) que decide quién puede leer o cambiar cada fila. Si está desactivado, tus tablas pueden estar abiertas para cualquiera que encuentre la dirección. Es el problema serio más común en apps generadas y permanece invisible hasta que miras.
Source maps publicados
Un «source map» revela el código original de tu app a cualquiera que abra las herramientas del navegador. Es útil mientras construyes, pero si llega a producción entrega a extraños una copia legible de cómo funciona tu app, y hace más fácil de encontrar cualquier otra brecha. Reeve comprueba si los tuyos están expuestos.
Rutas de API abiertas
Las apps de Next.js suelen incluir rutas de API: pequeños endpoints que hacen cosas como leer o escribir datos. Si una se generó sin comprobación de autenticación, puede responder a cualquiera que la llame. Reeve sondea si tus endpoints responden a extraños, sin usarlos nunca para cambiar nada.
Un archivo .env o de configuración expuesto
El archivo .env guarda las claves de un proyecto. A veces se publica por error con la app desplegada, y si es accesible es un atajo a todo lo sensible. Reeve comprueba si el tuyo está accesible sin que lo sepas.
Cabeceras de seguridad ausentes y compartición abierta (CORS)
Pequeños ajustes que le dicen a los navegadores cómo proteger a los visitantes, y si cualquier sitio puede llamar a los datos de tu app. Menores por sí solos; juntos amplían la brecha. 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.
v0 y Vercel siguen elevando la calidad de lo que se genera y despliega, y si usas Supabase, su propio asesor señala problemas de base de datos en el panel. Ambos ayudan. Lo que Reeve añade: tú trabajas en v0, no lees el código generado línea por línea, y esas herramientas hablan en lenguaje de desarrollador. Reeve mira toda la app desplegada desde fuera y te dice lo que encuentra en palabras sencillas. 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
¿El código de v0 está listo para producción y es seguro?
v0 produce código limpio y moderno, pero «parece listo para producción» no es lo mismo que «comprobado». La seguridad depende de cómo esté conectada la app: dónde viven las claves, si las reglas de tu base de datos están activadas, si los endpoints están protegidos. Reeve comprueba las partes expuestas gratis en unos 20 segundos.
¿Puede una app de v0 exponer mis claves de API?
Sí, si una clave acaba en un componente cliente o en un ajuste NEXT_PUBLIC_, Next.js los envía al navegador. No toda clave es un problema: algunas se supone que deben ser públicas. Reeve encuentra las claves en tu código cargado y te dice cuáles son seguras y cuáles deben moverse al servidor.
¿Son seguras las rutas de API de v0?
Pueden serlo, pero un endpoint generado a veces sale sin comprobación de autenticación, lo que significa que cualquiera que lo encuentre puede llamarlo. Reeve prueba si tus endpoints responden a extraños; solo comprueba que la puerta se abre, nunca la cruza.
¿Analizar mi app de v0 romperá algo?
No. Reeve solo mira lo que ya es público desde fuera. Nunca inicia sesión, nunca cambia nada y nunca descarga datos. Solo lectura, como comprobar si una puerta está cerrada sin entrar.
¿Qué hace en realidad el prefijo NEXT_PUBLIC_?
Le dice a Next.js que compile ese valor dentro del JavaScript que se envía al navegador. El valor deja de ser un ajuste del servidor y pasa a formar parte de tus archivos publicados, legible por cualquier visitante. Eso es correcto para una clave publicable y falso para una secreta, y el prefijo es lo único que lo decide.
Renombré una variable para añadirle NEXT_PUBLIC_ porque la app no podía leerla. ¿Me equivoqué?
Depende por completo de qué contenga la variable. Si era una clave publicable o una URL de proyecto, el cambio de nombre fue el arreglo correcto. Si era una clave secreta, la app no podía leerla porque nunca estuvo pensada para ejecutarse en el navegador, y el cambio de nombre la publicó. Renueva esa clave y luego mueve el código que la necesitaba a una ruta de servidor.
¿v0 configura por mí las reglas de mi base de datos?
Por sí solo no. v0 genera código de interfaz; la base de datos y sus reglas las montas tú donde las alojes. Si estás en Supabase, Row Level Security viene activado por defecto solo en las tablas creadas en el Table Editor del panel, y apagado en las creadas ejecutando SQL.