Node2Shell: el fallo Brotli de Node.js, quién está expuesto y cómo parchearlo
Node2Shell es el nombre que los investigadores dieron a CVE-2026-111497, un fallo en el decodificador Brotli que viene dentro de Node.js. El 21 de octubre de 2026 el proyecto Node.js lo corrigió en 22.23.4, 24.22.1 y 26.12.1. Una app que descomprime datos Brotli que otra persona puede enviar, como el cuerpo comprimido de una petición o una respuesta obtenida de otro servidor, puede caerse, filtrar memoria o ejecutar el código de un atacante. La corrección está en el propio Node.js, así que `npm update` no la aplica: hay que actualizar el runtime en todos los sitios donde se ejecuta.
Qué es Node2Shell
Brotli es un formato de compresión que usan los servidores web y los navegadores junto con gzip. Node.js incluye un decodificador Brotli en `node:zlib`. El aviso de Node.js describe el fallo: un cambio de bloque no válido en un flujo comprimido se trataba como una necesidad temporal de más datos en lugar de como un error de formato, así que el decodificador seguía añadiendo bytes a un búfer interno de ocho bytes y escribía más allá de su final. Una corrupción de memoria así puede tumbar el proceso, filtrar memoria o permitir a un atacante ejecutar código.
Node.js lo califica de alto y dice que permite la ejecución remota de código. Lo reportó OpenAI Codex Security. Después, los investigadores de Imperva lo reprodujeron como ejecución de código sin autenticación, y hay código de prueba de concepto público, así que trata como objetivo cualquier servicio Node.js sin parchear que procese datos de fuera.
¿Estás expuesto?
Un proceso Node.js está expuesto cuando él, o una librería que usa, descomprime datos Brotli que controla un atacante. Imperva probó dos formas habituales en que ocurre.
**Peticiones entrantes.** Express 5 y body-parser 2 descomprimen los cuerpos de petición enviados con `Content-Encoding: br`, porque la opción `inflate` de body-parser está activada por defecto. Así que una app con `app.use(express.json())` es alcanzable con una sola petición manipulada, antes de cualquier inicio de sesión.
**Peticiones salientes.** El `fetch()` integrado de Node pide y descomprime respuestas Brotli por su cuenta. Cualquier servidor al que llame tu código y que un atacante controle o haya comprometido llega al decodificador: webhooks a los que respondes, vistas previas de enlaces, scrapers, agentes de IA que obtienen las páginas que les da un usuario, sondeos de estado a otros sitios.
El código que llama directamente a las funciones Brotli de `node:zlib` con datos de fuera está expuesto de la misma forma. Los firewalls delante de tu app solo ven la primera vía: no pueden revisar lo que tu código obtiene de otros sitios.
Qué versiones lo corrigen
Cada línea de Node.js con soporte tiene una versión con la corrección (en la tabla). La misma versión corrige otras nueve vulnerabilidades, entre ellas tres fallos de certificados TLS y DNS calificados de altos, así que merece la pena aunque tu app nunca use Brotli.
Node.js 20 y anteriores no reciben corrección: están al final de su vida, y el proyecto Node.js dice que las versiones fuera de soporte siempre están afectadas cuando sale una versión de seguridad. Bun, que incluye su propio decodificador Brotli, corrigió el mismo fallo en 1.4.4.
Dónde se esconde Node.js
La actualización tiene que llegar a cada copia de Node que ejecuta tu código, y normalmente hay más de una.
**Imágenes de contenedor.** Un Dockerfile fijado a una versión exacta, como `node:24.22.0`, sigue siendo vulnerable por muchas veces que lo reconstruyas: cambia la versión a 24.22.1 o posterior. Las imágenes base que traen su propio Node (por ejemplo, las de pruebas con navegador) fijan la versión que había cuando se construyeron, así que actualiza Node también dentro de ellas.
**Servidores y CI.** El Node instalado con nvm, un gestor de paquetes o una acción de configuración de CI se actualiza ahí, y después se reinicia el servicio.
**Plataformas de hosting.** Vercel desplegó el 21 de octubre reglas de firewall contra la vía entrante para todos los proyectos y gestiona las versiones de parche de sus runtimes Node.js 22.x y 24.x, así que esos proyectos no necesitan cambiar de versión. Los proyectos que siguen en Node.js 20 deben pasar a 22.x o 24.x y volver a desplegar. Vercel también advierte de que su firewall no cubre las respuestas que tus funciones obtienen de otros servidores. En otros hostings, consulta el aviso de la propia plataforma sobre qué versión de Node ejecutan tus funciones.
**Apps creadas con IA.** Si un generador de apps con IA o un agente de programación escribió el código de servidor de tu app, la pregunta es la misma: qué runtime lo ejecuta y en qué versión. En monitorización de apps creadas con IA verás qué más vigilar cuando esté en producción.
Cómo comprobarlo
Ejecuta `node --version` en portátiles, runners de CI y servidores, y `docker run --rm <image> node --version` para cada imagen de contenedor. En un servicio en marcha puedes registrar `process.version` al arrancar. Todo lo que esté por debajo de la versión corregida de su línea, o en Node.js 20 o anterior, hay que actualizarlo.
Si no puedes actualizar hoy
Actualizar es la solución. Hasta que esté desplegado, puedes reducir la vía entrante: rechaza las peticiones con `Content-Encoding: br` en tu proxy o firewall, o pon `inflate: false` en body-parser y `express.json()`, lo que rechaza cualquier cuerpo de petición comprimido (comprueba antes que ninguno de tus clientes los envía).
No hay ningún ajuste que proteja la vía saliente, porque un servidor malicioso puede enviar una respuesta Brotli pida lo que pida tu código. Evita obtener URL no fiables desde servicios sin parchear hasta que estén actualizados.
Cómo ayuda Relvato
Relvato no puede leer desde fuera la versión de Node.js de un sitio, y no envía peticiones con forma de ataque para averiguarla, así que no señala Node2Shell directamente.
Lo que sí hace: el análisis de exposición señala una cabecera `X-Powered-By: Express`, que le dice a cualquier escáner cuál es tu stack (`app.disable("x-powered-by")` la quita). Y actualizar Node es un cambio como cualquier otro: con la revisión en cada despliegue desde GitHub, Relvato vuelve a ejecutar tus monitores tras el despliegue, para que sepas que el inicio de sesión, el checkout y tus páginas clave siguen funcionando con el nuevo runtime.
Relvato también funciona con Node.js. Sus monitores obtienen páginas de los sitios que vigilan, así que los pasamos a Node 24.22.1 la semana en que salió la corrección.
Runtimes con la corrección de Node2Shell
| Runtime | Corregido en | Nota |
|---|---|---|
| Node.js 26 | 26.12.1 | Línea actual |
| Node.js 24 | 24.22.1 | LTS |
| Node.js 22 | 22.23.4 | LTS |
| Node.js 20 y anteriores | Sin corrección | Fin de vida: actualiza a 22 o 24 |
| Bun | 1.4.4 | Incluye su propio decodificador Brotli |
Preguntas frecuentes
¿npm update corrige Node2Shell?
No. El fallo está en el propio Node.js, no en un paquete, así que actualizar las dependencias no lo cambia. Actualiza el runtime de Node.js a 22.23.4, 24.22.1 o 26.12.1 o posterior en todos los sitios donde se ejecuta tu código, y después reinicia o vuelve a desplegar.
No uso Express. ¿Estoy a salvo?
No necesariamente. El fetch() integrado de Node descomprime respuestas Brotli por defecto, así que el código que obtiene datos de servidores que no controlas está expuesto uses el framework que uses. Actualiza Node igualmente.
Mi app está en Vercel. ¿Tengo que hacer algo?
Con Node.js 22.x o 24.x, Vercel gestiona la versión de parche y tiene reglas de firewall contra cuerpos de petición manipulados, así que no hace falta cambiar de versión. Con Node.js 20, pasa a 22.x o 24.x y vuelve a desplegar. El firewall de Vercel no cubre las respuestas que tus funciones obtienen de otros servidores.
Uso Node.js 20 o 18. ¿Qué hago?
No reciben corrección: ambos están al final de su vida. Actualiza a Node.js 22 o 24, prueba y vuelve a desplegar.
¿Me protege un firewall de aplicaciones web?
Solo frente a peticiones manipuladas que entran. No ve las respuestas que tu código obtiene de otros servidores, que es la otra vía de entrada. Las reglas dan tiempo; la solución es actualizar.
Fuentes
- Node.js — Wednesday, October 21, 2026 Security Releases
- Imperva — Node2Shell: From Brotli Data to Remote Code Execution
- Vercel — Node.js security advisory: Brotli decoder RCE (CVE-2026-111497)
- Aikido — Node2Shell: Node.js Brotli vulnerability allows remote code execution and the fix
- body-parser — the inflate option (expressjs/body-parser)
- Bun — brotli: reject invalid block switch (CVE-2026-111497), oven-sh/bun #46351