← Blog
·7 min read

Variables de Entorno en Vercel: Qué es Seguro y Qué No

Vercel variables de entorno seguridad — qué expone NEXT_PUBLIC_, cómo configurar env por entorno, y cómo proteger secretos en edge functions. Con ejemplos reales.

Rod

Founder & Developer

Vercel variables de entorno seguridad — el error más frecuente que vemos no es dejar secretos en el repo. Es poner secretos en variables con el prefijo NEXT_PUBLIC_ y no entender que ese prefijo los hace completamente públicos.

NEXT_PUBLIC_MI_API_KEY=sk-xxxx en tu dashboard de Vercel parece estar guardado de forma segura. Pero durante el build, Next.js incrusta ese valor en el bundle de JavaScript que el browser descarga. Cualquier persona que abra las DevTools de tu app puede leerlo.

Este post explica qué es seguro, qué no, y cómo configurar cada tipo de secreto correctamente.


Cómo funciona NEXT_PUBLIC_ — y por qué expone tu variable

Next.js hace una distinción clara entre variables de servidor y variables de cliente.

Variables sin prefijo NEXT_PUBLIC_: Solo disponibles en el servidor — API routes, Server Components, getServerSideProps. El browser nunca las ve. Son las que debes usar para secretos.

Variables con prefijo NEXT_PUBLIC_: Next.js las reemplaza en el código durante el build con su valor literal. El resultado es que el bundle de JavaScript del browser contiene el valor, no una referencia a una variable de entorno.

// En tu código
const apiKey = process.env.NEXT_PUBLIC_STRIPE_KEY;
 
// En el bundle que el browser descarga (después del build)
const apiKey = "sk_live_xxxxxxxxxxxxxx"; // <- el valor literal está ahí

No importa dónde esté guardada la variable en Vercel. El prefijo NEXT_PUBLIC_ garantiza que el valor queda en el código del cliente.


Qué va con NEXT_PUBLIC_ y qué no

Variables que SÍ pueden ser públicas

# La URL de tu app — no es un secreto
NEXT_PUBLIC_APP_URL=https://tuapp.com
 
# La anon key de Supabase — diseñada para ser pública (si tienes RLS bien configurado)
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGci...
 
# La publishable key de Stripe — pública por diseño
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_xxxx
 
# Key de analytics como PostHog — pública por diseño
NEXT_PUBLIC_POSTHOG_KEY=phc_xxxx

La diferencia entre estas y las peligrosas es que sus proveedores las diseñaron para ser públicas. La anon key de Supabase, la publishable key de Stripe, y la key de PostHog tienen permisos limitados por diseño — no dan acceso administrativo aunque alguien las conozca.

Variables que NUNCA van con NEXT_PUBLIC_

# MAL: estas exponen acceso total
NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY=eyJhbGci...  # acceso sin RLS a toda tu BD
NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_xxxx          # puede cobrar y reembolsar
NEXT_PUBLIC_OPENAI_API_KEY=sk-proj-xxxx             # puede gastar todo tu crédito
NEXT_PUBLIC_DATABASE_URL=postgresql://user:pass@... # acceso directo a la BD
NEXT_PUBLIC_ANTHROPIC_API_KEY=sk-ant-xxxx           # acceso a la API de Claude
 
# BIEN: sin prefijo, solo disponibles en el servidor
SUPABASE_SERVICE_ROLE_KEY=eyJhbGci...
STRIPE_SECRET_KEY=sk_live_xxxx
OPENAI_API_KEY=sk-proj-xxxx
DATABASE_URL=postgresql://user:pass@...

Si una variable da acceso administrativo a cualquier servicio — elimina el NEXT_PUBLIC_.


Configurar env vars por entorno en Vercel

Vercel tiene tres entornos: Production, Preview, y Development.

  • Production — la versión que sirves en tu dominio principal
  • Preview — cada deploy de un PR o branch no-main genera una URL de preview
  • Developmentvercel dev en tu máquina local

Puedes configurar la misma variable con valores diferentes por entorno. Esto es importante para seguridad:

# Producción usa la base de datos real
DATABASE_URL=postgresql://prod-user:prod-pass@prod-host.com/prod-db
 
# Preview usa una base de datos de staging
DATABASE_URL=postgresql://staging-user:staging-pass@staging-host.com/staging-db

Para configurarlo en el dashboard de Vercel:

  1. Ve a tu proyecto > Settings > Environment Variables
  2. Agrega la variable
  3. Selecciona en qué entornos aplica (puedes deseleccionar Production para tener un valor diferente)
  4. Agrega otra entrada con el mismo nombre para los entornos restantes

Esto evita que un deploy de PR accidentalmente use credenciales de producción — un error más común de lo que parece.


El error de NEXT_PUBLIC_ en el archivo .env.local

Tu archivo .env.local no se sube a Git (si tienes el .gitignore correcto). Pero el riesgo es diferente: las variables NEXT_PUBLIC_ en .env.local se comportan igual que en producción — se incrustan en el bundle durante el build.

Si haces next build con NEXT_PUBLIC_MI_SECRETO=valor-real en tu .env.local, ese valor queda en los archivos de build. Si compartes esos archivos, subes la carpeta .next a algún lado, o expones el bundle de alguna forma — el secreto está expuesto.

La regla: NEXT_PUBLIC_ es para valores que puedes poner en un tweet sin preocuparte.


Variables de entorno en Edge Functions

Las Edge Functions de Vercel corren en el runtime de Edge — más ligero que Node.js, con algunas diferencias de API. Las variables de entorno funcionan igual que en el resto de Next.js:

// middleware.ts (corre en Edge runtime)
export function middleware(request: Request) {
  // process.env funciona en Edge Functions
  const webhookSecret = process.env.WEBHOOK_SECRET;
 
  // BIEN: variable de servidor, no expuesta al cliente
  if (!webhookSecret) {
    return new Response("Server error", { status: 500 });
  }
  // ...
}

Lo que no funciona en Edge runtime: algunas APIs de Node.js como fs o crypto tienen versiones limitadas. Pero process.env funciona sin problema.

Si tienes una Edge Function que necesita un secreto, configúralo en Vercel como variable de servidor (sin NEXT_PUBLIC_) y accédela con process.env.TU_VARIABLE.


Cómo saber si tu .env es accesible desde el exterior

Un error diferente — y más grave — es que el archivo .env esté en el servidor web y sea accesible públicamente. Esto pasa cuando tienes una configuración incorrecta de Nginx, un servidor de archivos estáticos mal configurado, o cuando subiste el .env al repo por accidente.

Si tienes dudas sobre si tu archivo .env es accesible desde tu URL de producción, el verificador de Data Hogo lo comprueba.

Verifica si tu .env está expuesto →


Checklist de seguridad para env vars en Vercel

Antes de hacer deploy, verifica:

  • Ninguna variable de secreto tiene el prefijo NEXT_PUBLIC_
  • El archivo .env (y .env.local, .env.production) está en .gitignore
  • Los entornos Production y Preview tienen valores diferentes para credenciales de base de datos
  • Las variables de entorno en Vercel están configuradas correctamente por entorno
  • Ningún secreto está hardcodeado en el código fuente (usa el scanner para verificarlo)

Para ese último punto — detectar secretos hardcodeados en tu repo — Data Hogo escanea tu código fuente buscando API keys, tokens y credenciales expuestas.

Escanea tu repo gratis →


Variables de entorno y el riesgo del historial de Git

Un punto que muchos olvidan: si en algún momento pusiste un secreto en una variable NEXT_PUBLIC_ y luego lo cambiaste, el valor antiguo puede estar en el historial de Git.

Borrar el valor del código actual no elimina los commits anteriores. Si tu repo es público — o si alguna vez lo fue — ese secreto puede estar indexado en algún lugar.

La solución si esto ya pasó:

  1. Rota el secreto inmediatamente en el proveedor (genera uno nuevo)
  2. Actualiza la variable en Vercel con el nuevo valor
  3. Si necesitas limpiar el historial de Git, usa git filter-repo — pero ten en cuenta que reescribe la historia del repo

Para entender cómo funciona la seguridad de secretos más allá de Vercel, nuestra guía de ciberseguridad para programadores principiantes explica los conceptos base con ejemplos de código.


Preguntas frecuentes

¿Qué expone NEXT_PUBLIC_ en Next.js?

Cualquier variable con el prefijo NEXT_PUBLIC_ se incrusta en el bundle de JavaScript del cliente durante el build. Eso significa que cualquier persona que abra las DevTools de tu app en producción puede ver el valor. Solo usa NEXT_PUBLIC_ para valores que genuinamente son públicos — como la URL de tu app o la anon key de Supabase.

¿Es segura la NEXT_PUBLIC_SUPABASE_ANON_KEY?

Sí, si tus Row Level Security (RLS) policies de Supabase están correctamente configuradas. La anon key es pública por diseño — Supabase la diseñó para usarse en el cliente. Lo que la protege no es que sea secreta, sino que RLS restringe qué puede hacer con ella.

¿Cómo protejo un secreto en una Edge Function de Vercel?

Configura la variable en el dashboard de Vercel como variable de entorno de servidor (sin el prefijo NEXT_PUBLIC_). En tu Edge Function, accédela con process.env.TU_SECRETO. Vercel inyecta las variables de entorno en el runtime de Edge Functions sin exponerlas al cliente.

¿Puedo tener diferentes valores de env vars para producción y preview en Vercel?

Sí. En el dashboard de Vercel, cuando agregas una variable de entorno puedes seleccionar a qué entornos aplica: Production, Preview, Development. Puedes tener la misma variable con valores diferentes por entorno. Útil para usar una base de datos de staging en previews y la de producción solo en el entorno Production.

¿Vercel encripta mis variables de entorno?

Sí. Vercel encripta las variables de entorno en reposo y en tránsito. No son visibles en los logs de build por default. Pero recuerda: si usas NEXT_PUBLIC_, el valor queda en el bundle del cliente — la encriptación de Vercel no aplica una vez que el valor está en el JavaScript que el browser descarga.

vercelvariables de entornonext_publicseguridadenv varstutoriales