En 2003, cuando administraba el cyber café a los 16 años, aprendí algo que tardé veinte años en formular con palabras: la confianza sin modelo es negligencia con buena prensa. Teníamos ocho máquinas conectadas por un switch de 10/100 y una sola salida a internet. Cuando se caía la conexión a las 11pm con el local lleno, yo tenía que diagnosticar en cinco minutos o mi viejo perdía plata. Aprendí a no confiar en nada que no pudiera trazar: ni el router, ni el ISP, ni el cableado. Todo tenía que ser verificable. Todo tenía que tener un camino de falla conocido.
Veinte años después, puse infra crítica en Vercel y asumí que el modelo de amenazas venía incluido en el plan Pro.
No venía.
Vercel breach supply chain: qué pasó y qué no importa
En abril de 2026, Vercel confirmó un incidente de seguridad con componente de supply chain. Los detalles técnicos exactos todavía se están destilando entre NDA, postmortem corporativo y especulación de Twitter. Hay análisis del qué por todos lados. No voy a repetirlos.
Lo que me interesa es el por qué yo no estaba preparado para pensar en ese escenario. Y la respuesta es incómoda: porque Vercel hace tan bien su trabajo de abstraer complejidad que yo asumí, implícitamente, que también abstraía el riesgo.
No lo hace. Ninguna plataforma lo hace. Nunca lo hicieron.
El problema no fue el incidente. El problema fue mi negligencia epistémica: la decisión activa —aunque inconsciente— de no modelar amenazas en capas que yo no controlaba directamente.
Por qué terciarizamos el modelo de amenazas junto con el deployment
Vercel es genuinamente brillante. Edge functions, ISR, deployment atómico, preview environments, integración con GitHub que funciona de verdad. Es el tipo de herramienta que hace que un developer solo pueda operar con la superficie de un equipo mediano. Entiendo por qué confié.
Pero hay un patrón cognitivo peligroso que estas plataformas habilitan sin querer:
Si no veo la complejidad, asumo que no existe el riesgo.
Vercel oculta Nginx, oculta el routing, oculta el CDN, oculta los certificados, oculta el build pipeline. Eso es valor real. El problema es que cuando algo está oculto, también está fuera de tu modelo mental de falla.
Yo tenía un threat model para mi código. Tenía uno para mi base de datos en Railway. No tenía ninguno para mi build pipeline en Vercel. Y eso es exactamente el vector que supply chain attacks explotan: el espacio entre lo que vos controlás y lo que asumís que alguien más controla.
// Lo que yo modelaba como superficie de ataque
const miModeloDeAmenazas = {
inputsDeUsuario: 'sanitizados ✓',
autenticacion: 'JWT con rotación ✓',
baseDeDatos: 'queries parametrizadas ✓',
secretsEnvVars: 'Railway secrets manager ✓',
// Lo que no modelaba
buildPipeline: undefined, // ← acá
dependenciasDeCI: undefined, // ← y acá
infraDeVercel: undefined, // ← y especialmente acá
supplyChainDeNPM: 'npm audit... suficiente, ¿no?'
};
Ese undefined no significa que yo pensé en eso y decidí no cubrirlo. Significa que nunca apareció en mi cabeza como superficie de ataque posible. Y esa es exactamente la diferencia entre riesgo aceptado y riesgo ignorado.
El pragmatismo como excusa epistémica
Acá viene la parte que me cuesta más admitir.
Si alguien me hubiera preguntado en marzo de 2026 "¿modelaste el riesgo de supply chain en tu build pipeline?", yo hubiera respondido algo como: "Soy un developer solo, no tengo tiempo para eso. Uso Vercel precisamente para no tener que pensar en esas capas."
Eso suena razonable. Incluso maduro. "Conocé tus límites, usá abstracciones."
Pero es una trampa. Porque hay una diferencia enorme entre:
Riesgo aceptado conscientemente: "Sé que Vercel puede tener incidentes, evalué la probabilidad y el impacto, y decidí que el valor que aporta supera el riesgo residual."
Riesgo ignorado por comodidad: "Vercel se ocupa de eso."
Yo estaba haciendo lo segundo y llamándolo lo primero.
Es lo mismo que confiar ciegamente en herramientas de configuración sin entender qué hacen internamente. La abstracción no elimina el riesgo, lo desplaza. Y si no sabés adónde se desplazó, no podés responder cuando aparece.
Supply chain attacks: el vector que más explota la confianza delegada
Los supply chain attacks son devastadores precisamente porque atacan el modelo de confianza transitiva. Yo confío en Vercel. Vercel confía en sus dependencias. Sus dependencias confían en otras. En algún punto de esa cadena, alguien inserta código malicioso.
El ataque no necesita romper mi código. Solo necesita comprometer algo en lo que yo confío sin verificar.
# Superficie de ataque que yo no estaba monitoreando
# Build pipeline de Vercel
# ↓
# Dependencias del build runner
# ↓
# Paquetes npm que se instalan en CI
# ↓
# Scripts de postinstall (frecuentemente ignorados)
# ↓
# Acceso a env vars durante el build ← el premio
Y acá está el punto que más me incomoda: mis env vars —incluyendo secrets de producción— están disponibles durante el build. Eso es necesario para que el build funcione. Pero también significa que cualquier código que corra durante el build tiene acceso a ellas.
Yo sabía esto técnicamente. No lo había conectado con mi modelo de amenazas. Esa desconexión entre conocimiento técnico y razonamiento de seguridad es lo que llamo negligencia epistémica.
No es distinto al problema que describí con agentes que pasan tests vacíos: el sistema te da señales de que todo está bien, y vos dejás de mirar.
Qué cambié después del incidente
No me fui de Vercel. Eso sería el equivalente a tirar la computadora después de un virus. La plataforma sigue siendo la mejor opción para lo que hago.
Lo que cambié fue el modelo mental:
1. Documenté el threat model explícitamente, incluyendo capas que no controlo
## Superficies de ataque — [proyecto]
### Capas que controlo
- Código de la aplicación
- Queries a la base de datos
- Autenticación y autorización
- Validación de inputs
### Capas que delego (con riesgo conocido)
- Build pipeline: Vercel — riesgo: supply chain en CI
Mitigación: env vars separadas por ambiente, rotación periódica
- CDN y routing: Vercel — riesgo: DDoS, inyección de contenido
Mitigación: CSP headers, SRI en assets críticos
- Base de datos: Railway — riesgo: breach en proveedor
Mitigación: backups propios, encryption at rest verificado
### Riesgos aceptados sin mitigación activa
- Compromiso total de Vercel como proveedor
Justificación: improbable, plan de contingencia existe pero no está activo
Este documento no me protege de un ataque. Me protege de sorprenderme.
2. Separé secrets de build de secrets de runtime
Lo que el build necesita para compilar no debería ser lo mismo que la aplicación necesita para correr. En teoría lo sabía. En práctica tenía todo mezclado en el mismo .env.
// Antes: todo junto, todo disponible en build
VERCEL_ENV=production
DATABASE_URL=postgresql://... // ← no debería estar en build
NEXT_PUBLIC_API_URL=https://api.ejemplo.com
STRIPE_SECRET_KEY=sk_live_... // ← definitivamente no
// Después: separado por necesidad real
// Variables de BUILD (solo lo que el compilador necesita)
NEXT_PUBLIC_API_URL=https://api.ejemplo.com
NEXT_PUBLIC_POSTHOG_KEY=phc_...
// Variables de RUNTIME (inyectadas en el servidor, no en build)
// DATABASE_URL, STRIPE_SECRET_KEY, etc. — via Railway env
3. Empecé a auditar postinstall scripts
# Revisar qué se ejecuta en npm install
npm pack --dry-run
cat node_modules/[paquete-critico]/package.json | jq '.scripts'
# Ver qué paquetes tienen scripts de install
cat package-lock.json | jq '[.packages | to_entries[] | select(.value.scripts.postinstall or .value.scripts.preinstall) | .key]'
Es tedioso. No lo voy a hacer para los 847 paquetes en mi node_modules. Pero sí para las dependencias directas críticas.
Esto conecta con algo que escribí sobre diseño de sistemas confiables: la confiabilidad no viene de no tener fallas, viene de saber cómo fallan las cosas y tener respuesta para eso.
4. Agregué SRI para assets externos
<!-- Sin SRI: confío en que el CDN externo no fue comprometido -->
<script src="https://cdn.externo.com/libreria.js"></script>
<!-- Con SRI: el browser verifica el hash antes de ejecutar -->
<script
src="https://cdn.externo.com/libreria.js"
integrity="sha384-[hash]"
crossorigin="anonymous"
></script>
No es la solución completa. Es una capa más en el modelo.
El costo real de comprimir el modelo de amenazas
Hay un paralelo con algo que analicé sobre optimización semántica de prompts: cuando comprimís agresivamente, perdés contexto que parecía redundante pero no lo era. Los threat models tienen el mismo problema. Cuando los simplificás por comodidad, el contexto que perdés es exactamente el que ataca primero.
Y sobre quién decide qué es legible o qué cuenta como "suficiente seguridad": eso también es una decisión de poder. Los que diseñan las abstracciones deciden qué hacés visible. Vercel decidió que el build pipeline fuera invisible. Es una decisión válida para UX. No es una decisión de seguridad.
FAQ — Vercel breach supply chain
¿Qué pasó exactamente en el incidente de Vercel de abril 2026?
Vercel confirmó un incidente de seguridad con componente de supply chain en abril de 2026. Los detalles técnicos completos están siendo divulgados de forma gradual. Lo confirmado incluye acceso no autorizado en algún punto de la cadena de build/delivery. Para detalles actualizados, seguí el postmortem oficial en el blog de seguridad de Vercel.
¿Tengo que migrar de Vercel después de este incidente?
Depende de tu modelo de amenazas, no del incidente en sí. Vercel sigue siendo una plataforma técnicamente sólida. La pregunta relevante no es "¿es segura Vercel?" sino "¿entiendo cuáles son mis riesgos residuales al usarla?" Si la respuesta es no, eso es el problema a resolver, independientemente del proveedor.
¿Qué es un supply chain attack y por qué es diferente a un hack convencional?
Un supply chain attack no ataca tu código directamente. Compromete algo en la cadena de dependencias entre lo que vos escribís y lo que el usuario final ejecuta: una librería de npm, un build runner, un CDN, una action de GitHub. Es más difícil de detectar porque el vector de ataque está en código que vos asumís confiable sin verificar activamente.
¿Cómo sé si mis proyectos en Vercel fueron afectados?
Revisá los logs de deployment del período reportado, rotá todos los secrets que estuvieran disponibles durante builds de ese período, y activá alertas en tus proveedores de base de datos y servicios externos para accesos inusuales. Si tenés Vercel Pro o Enterprise, el soporte de seguridad puede darte más contexto sobre tu cuenta específica.
¿Alcanza con npm audit para protegerme de supply chain attacks?
No. npm audit revisa vulnerabilidades conocidas en dependencias. Un supply chain attack generalmente usa código que no tiene vulnerabilidades reportadas — el problema es que el código fue maliciosamente modificado, no que tenga un bug conocido. Son vectores distintos. npm audit es necesario pero no suficiente.
¿Qué es lo mínimo que debería hacer para mejorar mi postura frente a supply chain attacks en Vercel?
Tres cosas concretas: separar secrets de build de secrets de runtime, auditar postinstall scripts de dependencias directas críticas, y documentar explícitamente qué riesgos estás delegando a Vercel versus cuáles estás mitigando vos. No es blindaje completo, pero convierte riesgo ignorado en riesgo conocido.
Lo que haría diferente
No dejaría de usar Vercel. Pero desde el primer proyecto incluiría un documento de threat model que tenga una sección explícita para "capas que delego con riesgo conocido". No para resolverlas todas, sino para no sorprenderme.
El cyber café me enseñó que los sistemas fallan de maneras específicas y que conocer esas maneras es la diferencia entre diagnóstico y pánico. Tardé veinte años en aplicar esa lección a cómo uso plataformas de deployment.
El incidente de Vercel no me rompió nada concreto. Me rompió la excusa de que "usar buenas plataformas" es equivalente a "tener modelo de seguridad". No lo es. Nunca lo fue.
La abstracción es valor. La confianza ciega en la abstracción es deuda técnica de seguridad que eventualmente se cobra.
¿Tenés un threat model documentado para las plataformas que usás, o también lo estás terciarizando? Me interesa saber cómo lo resolvieron otros developers que trabajan solos o en equipos chicos.
Este artículo fue publicado originalmente en juanchi.dev
Top comments (0)