Variables de entorno y secretos: dónde viven las claves de tu app

Qué valores van fuera del código, qué claves pueden ir en el navegador y cuáles no, y qué revisar cuando una IA escribe la configuración de tu app.

info Definición Rápida
Las variables de entorno son valores de configuración guardados fuera del código, como la dirección de una base de datos o una clave de servicio. Un secreto es el subconjunto que da acceso: si alguien lo obtiene, puede actuar como tu app. Separar ambos del código es una de las medidas más básicas de seguridad.

¿Qué va en el código y qué va fuera?

La metodología Twelve-Factor, una guía clásica para aplicaciones modernas, define la configuración como todo lo que puede cambiar entre despliegues: direcciones de base de datos, credenciales de servicios externos y el nombre del servidor, por ejemplo. Propone guardarla en variables de entorno por tres razones: se cambian sin tocar el código, es poco probable subirlas al repositorio por accidente y son un estándar que no depende del lenguaje ni del sistema operativo. Su prueba de fuego: el repositorio debería poder hacerse público en cualquier momento sin comprometer ninguna credencial (Twelve-Factor App, Config).

Lo que no cambia entre despliegues, como la estructura de rutas de la app, sí puede vivir en el código. La regla práctica: si cambia según el entorno o da acceso a algo, va fuera.

Las variables de entorno son el mínimo, no el techo. La guía de OWASP advierte, en su sección sobre contenedores, que suelen ser accesibles para todos los procesos y pueden acabar en registros o volcados del sistema, y prefiere inyectar el secreto como archivo o en memoria (OWASP, Secrets Management Cheat Sheet). Stripe indica algo parecido: usar el gestor de secretos de tu plataforma y, si no hay uno, variables de entorno (Stripe, API keys). Para una web pequeña, las variables de tu plataforma de despliegue son un punto de partida razonable; escribir la clave en el código nunca lo es.

¿Qué es un secreto y qué clave puede ir en el navegador?

Un valor público, como el nombre de la app, se puede ver sin problema. Un secreto, como la clave de una API de pagos, no: quien la tenga puede hacer llamadas en tu nombre, gastar tu cuota o leer datos. Por eso plataformas como Vercel distinguen dos tipos al guardar una variable: las de configuración, que siguen legibles para quienes tienen acceso al proyecto, y los secretos, que después de guardarlos solo se pueden reemplazar, no leer (Vercel, Environment variables).

La pregunta clave es si el valor viaja al navegador. En Next.js, las variables sin el prefijo NEXT_PUBLIC_ solo existen en el servidor; las que lo llevan se copian dentro del JavaScript que recibe el navegador en el momento de construir la app (Next.js, Environment variables). Poner una clave secreta con ese prefijo equivale a publicarla.

No todas las claves son secretas. Stripe lo explica bien: su clave publicable (pk_) es segura de exponer y está pensada para el código del navegador y las apps móviles; las claves secretas (sk_) y las restringidas (rk_) no, y solo deben vivir en el servidor (Stripe, API keys). Cada proveedor tiene su propia regla, así que antes de poner una clave en el navegador comprueba en su documentación que esa clave en concreto es pública. Si dudas, trátala como secreta.

¿Cómo se manejan los entornos: producción, vista previa y local?

Una misma variable puede tener valores distintos según el entorno. En Vercel puedes definirlas para producción, para vista previa (cualquier rama que no sea la de producción) y para desarrollo local; una variable específica de una rama reemplaza a la general de vista previa (Vercel, Environment variables). Así las vistas previas usan una base de datos de prueba y solo producción usa la real.

OWASP va en la misma línea: el secreto debería ser distinto en cada entorno, y conviene separar los de producción de los de desarrollo. Usar la clave de producción en tus pruebas es el error contrario.

Dos detalles prácticos. Un cambio en una variable no afecta a los despliegues que ya existen: se aplica al siguiente, así que hay que volver a desplegar. Y en GitHub Actions los secretos se guardan por repositorio, entorno u organización, y no se entregan al ejecutor cuando el flujo lo dispara un repositorio bifurcado, salvo el GITHUB_TOKEN (GitHub, Using secrets in GitHub Actions).

¿Qué revisar cuando una IA escribe la configuración?

Cuando un agente crea un archivo de configuración o un formulario que llama a un servicio, revisa cinco cosas:

  1. Que la clave no aparezca escrita en un archivo de código. Debe leerse desde una variable.
  2. Que el archivo de ejemplo no tenga valores reales. Un .env.example solo muestra nombres y pistas, con marcadores como TU_CLAVE_AQUI.
  3. Que la clave del navegador sea una pública. Según el proveedor, algunas claves están pensadas para el cliente y otras no (ver arriba).
  4. Que el repositorio ignore los archivos locales de configuración. Next.js avisa de que casi nunca quieres subir los archivos .env, y su plantilla inicial ya los añade a .gitignore (Next.js).
  5. Que el agente no lea lo que no necesita. Claude Code permite bloquear la lectura con reglas de denegación, por ejemplo Read(./.env); según su documentación, esas reglas cubren sus herramientas de archivos y comandos de shell reconocidos como cat, pero no un script que abre archivos por su cuenta. Para un bloqueo a nivel de sistema operativo hay que activar el sandbox (Claude Code, Permissions).

Y un hábito más: no pegues una clave real en el chat ni en un prompt.

¿Qué hago si una clave se filtró?

Supón que una clave se subió a un repositorio o apareció en una captura. El orden importa:

  1. Revócala o rótala en el servicio que la emitió. GitHub la presenta como el primer paso: una vez revocada o rotada, ya no sirve para acceder. Reescribir el historial del repositorio puede no ser necesario, y además no alcanza copias ajenas como bifurcaciones o clones (GitHub, Removing sensitive data from a repository). OWASP también pide revocar de inmediato las claves expuestas.
  2. Pon la nueva clave en tu plataforma y vuelve a desplegar. Vercel recomienda generar la nueva, actualizarla en el proyecto, redesplegar, comprobar que funciona y solo entonces invalidar la antigua, para no dejar la app caída (Vercel, Rotating environment variables).
  3. Revisa los registros del proveedor, si los ofrece, por si alguien usó la clave vieja.

Para prevenirlo, GitHub bloquea por defecto los envíos con secretos a repositorios públicos desde tu cuenta (la protección de envíos de usuario), mientras que la del repositorio hay que activarla (GitHub, Push protection).

Ejemplo

Ejemplo ilustrativo: una diseñadora genera con IA una página que muestra el clima de un evento. La IA escribe la clave de la API meteorológica directamente en el archivo de la página. Ella la detecta buscando las palabras key y token en la carpeta del proyecto, antes de publicar. Le pide al agente tres cambios: leer la clave desde una variable de entorno, hacer la llamada desde una función del servidor y no desde el navegador, y dejar en .env.example solo la línea WEATHER_API_KEY=TU_CLAVE_AQUI. Como la clave ya estuvo escrita en un archivo que pudo copiarse o subirse, genera una nueva en el panel del proveedor, la guarda como secreto en la plataforma de despliegue, vuelve a desplegar y revoca la anterior.

Errores comunes

  • Escribir una clave directamente en el código de la página.
  • Subir un archivo .env con valores reales al repositorio.
  • Usar la clave de producción en las pruebas o en las vistas previas.
  • Creer que borrar la clave del código basta si ya se publicó: hay que revocarla y reemplazarla.
  • Poner una clave secreta en una variable con prefijo público, como NEXT_PUBLIC_.
  • Cambiar una variable y no volver a desplegar.
  • Invalidar la clave vieja antes de desplegar la nueva y dejar la app sin servicio.

Para seguir: leer código sin saber programar, deploy para diseñadores, qué es el vibe coding y Claude Code.

Fuentes

Preguntas frecuentes

¿Qué es una variable de entorno?
Es un par clave-valor guardado fuera del código, que la app lee al ejecutarse. Sirve para cambiar valores entre entornos, como la base de datos de pruebas o la de producción, sin tocar el código.
¿Qué es un secreto en una app?
Es un valor que da acceso a un servicio, como una clave de API, un token o una contraseña. Si alguien lo obtiene, puede usar el servicio como si fuera la app.
¿Por qué una clave secreta no debe estar en el código del navegador?
Porque el código que llega al navegador lo puede leer cualquiera que lo abra. Una clave secreta ahí es, en la práctica, una clave pública. Solo van en el navegador las claves que el proveedor diseñó para eso, como la clave publicable de Stripe.
¿Qué pasa con las variables cuando cambio su valor?
En plataformas como Vercel, el cambio se aplica a los despliegues nuevos, no a los anteriores. Hay que volver a desplegar para que la app use el valor nuevo.
¿Qué hago si subí una clave por error?
Primero revócala o rótala en el servicio que la emitió: con eso deja de servir, aunque siga en el historial del repositorio. Después la reemplazas en tu plataforma y vuelves a desplegar.