← Blog
2026-08-24Lectura de 7 min

Tu .env no te protege: cómo saber qué llaves estás publicando

Una sola herramienta de IA bloqueó más de 17,000 despliegues en 30 días porque llevaban llaves expuestas. El dato es de Vercel, sobre su propio v0. No es un descuido de principiantes: es lo que pasa por defecto cuando escribes software con IA.

Y la mayoría de esas llaves estaban en un .env, que es justamente donde todo el mundo cree que están a salvo.

Qué es realmente un .env

Un .env es un archivo de texto plano con una lista de variables. Nada más. No está cifrado, no tiene permisos especiales y no lo protege nadie. Lo único que hace por ti es sacar los valores del código para que no se te escapen al copiar y pegar.

Que una llave esté ahí adentro no la vuelve secreta. Lo que decide si es secreta o no es dónde termina — y ahí hay dos caminos completamente distintos.

El prefijo que lo cambia todo

Esta es la parte que casi nadie te explica, y es la que importa. Las herramientas de build tienen una regla: sólo meten en tu sitio las variables que llevan cierto prefijo. Las demás se quedan fuera.

HerramientaSe publica en el navegadorSe queda del lado del servidor
Vite (Lovable, Bolt, la mayoría)VITE_…todo lo demás
Next.js (v0)NEXT_PUBLIC_…todo lo demás
Create React AppREACT_APP_…todo lo demás

Léelo al revés, porque así es como duele: si tu variable lleva ese prefijo, su valor queda escrito dentro del JavaScript que descarga cualquiera que abra tu sitio. No es un riesgo teórico ni depende de que alguien "hackee" algo: está en el archivo, en texto, a la vista.

Y el prefijo no lo pusiste tú por gusto: lo puso la IA porque sin él la variable no funciona en el navegador. Así que el código que "por fin funcionó" es exactamente el que publica la llave.

Revísalo tú, en dos minutos

No necesitas herramientas. En tu sitio ya publicado:

  1. Abre tu sitio y presiona Ctrl+U (o Cmd+Option+U en Mac) para ver el código fuente.
  2. Busca la carpeta assets y abre cualquier archivo .js.
  3. Con Ctrl+F, busca un pedazo de tu llave — los primeros ocho caracteres bastan.
  4. Si aparece, está publicada. Fin de la discusión.

Prueba también esto en la barra de direcciones: tusitio.com/.env. Si te descarga un archivo en vez de darte un error, tu .env completo está en internet — eso pasa cuando se sube la carpeta del proyecto sin filtrar y el archivo viaja con ella.

No todas las llaves son un problema

Aquí es donde la mayoría de los consejos que vas a encontrar exageran. Hay llaves diseñadas para ser públicas, y verlas en tu código no significa que estés en peligro:

  • Sí son públicas por diseño: la clave anon de Supabase, la API key de Google Maps, la clave publicable de Stripe (pk_…), el token de un servicio de analítica. Van en el navegador a propósito — su protección no es el secreto, son las restricciones que les pongas.
  • Nunca deben salir: la service_role de Supabase, cualquier sk_… de Stripe, tokens de OpenAI o Anthropic, credenciales de base de datos, llaves de AWS. Estas dan acceso completo, sin límite y sin registro de quién fue.

La regla corta: si el nombre trae secret, service, private o empieza con sk_, no va en el navegador jamás. Y si trae public, anon o publishable, va — pero configúrale sus restricciones.

Restringir lo que sí es público

Una llave pública sin restricciones es una llave que alguien más puede usar a tu costa. Dos cosas que toman cinco minutos:

  • Restricción por dominio. Google Maps y casi todos los servicios te dejan decir "esta llave sólo funciona si la petición viene de mi-sitio.com". Sin eso, alguien la copia y tu factura crece con el tráfico de otro.
  • Reglas de acceso a los datos. En Supabase, la clave anon es segura *sólo* si activaste Row Level Security. Sin RLS, esa llave pública lee toda tu base de datos. Es el error más caro de la lista, y no lo detecta ningún escáner: hay que activarlo.

Si ya la publicaste

Pasa. Lo importante es el orden — y el primer paso no es el que la gente hace primero:

  1. Rota la llave primero. Entra al servicio, genera una nueva y desactiva la vieja. Mientras la vieja siga viva, borrarla de tu código no sirve de nada.
  2. Después arregla el código. Saca el valor, usa la variable, vuelve a publicar.
  3. Revisa el historial de Git. Si el .env estuvo alguna vez en un commit, sigue ahí aunque lo hayas borrado después. Un repositorio público con historial es una llave regalada.
  4. Revisa el consumo del servicio. Si alguien la usó, se ve en el uso — picos raros, peticiones desde países donde no tienes usuarios.

Qué revisa FluentOps, y qué no

En cada publicación, en todos los planes —también el gratuito— se revisa lo que estás por publicar y lo que quedó publicado:

  • Archivos de secretos (.env y similares): en el código fuente es una advertencia; en el sitio publicado es severidad alta, porque es descargable ahora mismo.
  • Llaves escritas en el código: access keys de AWS, bloques de llave privada, JWT, credenciales dentro de una URL.
  • Código expuesto: la carpeta .git descargable, y los *source maps* — tu código original sin minificar, al alcance de cualquiera.
  • Dependencias vulnerables: en Node se corre npm audit sobre el árbol completo, directas y transitivas. Un proyecto real mostraba 1 vulnerabilidad leyendo sólo el manifiesto; el árbol completo tenía 3.

Y los límites, porque prometer de más en seguridad es peor que no revisar: los valores de los secretos siempre salen redactados, se revisan archivos de texto (los binarios se saltan), hay un tope de 50 hallazgos, y fuera de Node el escaneo de dependencias es de las directas. Nada de esto reemplaza activar RLS ni restringir tus llaves públicas — eso es tuyo.

Lo que sí es distinto

Otras plataformas también buscan secretos: Netlify falla tu build si detecta uno, y Vercel bloquea despliegues de v0 por lo mismo. Comparar función por función no dice gran cosa. Lo que sí dice algo es el conjunto, y sobre todo qué pasa cuando llegas al límite del plan gratuito:

  • Revisar tus llaves en el código y en lo publicado, con severidad distinta según dónde estén.
  • Decirte si tu carpeta .git o tus *source maps* quedaron descargables. (Vercel te deja proteger los source maps; eso es distinto de avisarte que los publicaste.)
  • Revisar tus dependencias vulnerables en cada deploy, con el árbol completo. Ninguna de las dos lo hace de fábrica: eso vive en integraciones que tú instalas.
  • Generar el SEO técnico que tu sitio no trae — sitemap, robots, OG, description, favicon — sin que instales un plugin.
  • Y no apagarte el sitio. Netlify pausa todos los sitios de la cuenta al agotar los créditos del mes; el plan Hobby de Vercel pausa al topar el cap.

Ese último punto es el que sostiene la palabra "gratis". Una plataforma que te revisa el código pero te apaga el sitio cuando se acaban los créditos no te lo está dando gratis: te lo está prestando. Dime otra que haga las cinco.

No hay nada que configurar ni que activar. Si nunca en tu vida corriste npm audit, esto es lo primero que te lo va a decir.

Y si tu proyecto todavía no está en línea, aquí está cómo publicarlo — con la revisión incluida desde el primer deploy.

Revisa tu sitio gratis →

Pruébalo con tu propio proyecto.

Arrastra tu carpeta o pega tu repo. Detectamos tu stack, lo construimos y te damos una URL pública — gratis, sin tarjeta, y tu sitio nunca se pausa.

Empieza gratis
Sigue leyendo
Cómo agregar un formulario a un sitio estático sin backend