26 de octubre de 2026 7 min de lectura

CVE-2026-111497: Una vulnerabilidad en el decodificador Brotli afecta a Node.js, Bun, Python, .NET y Envoy: qué debe actualizar ahora

Un fallo en el decodificador Brotli de Google (versiones 1.0.3 a 1.2.0) permite, mediante datos manipulados, una escritura fuera de límites que puede llegar a la ejecución de código (CVE-2026-111497, CVSS 9.2). Está afectado cualquier software que descomprima datos Brotli procedentes de fuentes externas: Node.js, Bun, Python con Brotli/brotlicffi, .NET, Envoy y curl. Hay actualizaciones disponibles.

El decodificador Brotli de Google contiene un error en las versiones 1.0.3 a 1.2.0 por el que datos Brotli manipulados sobrescriben memoria fuera de un búfer. La vulnerabilidad tiene el identificador CVE-2026-111497 y una puntuación de 9.2 según CVSS 4.0; públicamente se conoce con los nombres Node2Shell y Broccoli2Shell. Las posibles consecuencias son un bloqueo, la lectura de memoria de proceso o la ejecución de código. Imperva ha demostrado ejecución de código en Node.js 24.22.0 sin modificar. El código de prueba de concepto es parcialmente público, pero hasta ahora no se conocen ataques activos. Node.js publicó las correcciones el 21 de octubre de 2026; los demás ecosistemas le siguieron hasta el 26 de octubre.

Tras el aviso, revisé mis propios sistemas: el runner de compilación de este sitio web seguía ejecutando Node.js 22.23.1, aunque la versión 22.23.4 llevaba días disponible. El motivo se explica en la sección sobre GitHub Actions más abajo; afecta a cualquier runner autohospedado con actions/setup-node.

Ayuda con el inventario y la actualización

Si necesita ayuda para localizar componentes afectados en aplicaciones, imágenes de contenedor o canalizaciones de CI, utilice el formulario de contacto en adeptio.ch. También puedo responder con poca antelación.

Causa

El error se encuentra en la función DecodeBlockTypeAndLength(). Esta procesa los cambios de bloque en el flujo de datos comprimidos, es decir, los puntos en los que el decodificador cambia a otro código Huffman. En las versiones vulnerables, la función solo devuelve un valor booleano; BROTLI_FALSE significa tanto «flujo de datos defectuoso» como «se necesita más entrada». Un flujo de datos manipulado declara un único tipo de bloque y agota su longitud, forzando así un cambio que no puede completarse. El decodificador lo trata como falta de entrada, añade más bytes a un búfer interno de 8 bytes y escribe más allá de su final.

La corrección upstream (commit 0ed4268 en el repositorio google/brotli) introduce un código de error propio BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH y aborta la decodificación. OpenAI Codex Security notificó el error ya en febrero de 2026. La corrección llegó entonces al código fuente, pero no se clasificó como corrección de seguridad ni apareció en ninguna versión publicada. Solo se distribuyó con Brotli 1.2.1 y las versiones de Node.js del 21 de octubre de 2026.

Cuándo un sistema es vulnerable

Comprimir con Brotli es inocuo; solo es vulnerable quien descomprime datos Brotli de una fuente externa. Hay dos vías:

  • Cliente: La aplicación solicita una URL y decodifica una respuesta con Content-Encoding: br. El fetch() integrado de Node.js y Bun lo hace automáticamente y no se puede desactivar. Por tanto, se ven afectados los rastreadores, los receptores de webhooks con devolución de llamada, las vistas previas de enlaces, los scripts de monitorización y toda automatización que cargue contenido de servidores de terceros. Para ello, un atacante solo necesita controlar uno de los servidores consultados.
  • Servidor: Un framework o middleware descomprime cuerpos de solicitud con Content-Encoding: br. Imperva menciona para Node.js body-parser 2.0.0 a 2.3.0 y Express 5.0.0 a 5.3.0 con los analizadores configurados json() o raw(). Un servidor http básico de Node.js no decodifica por sí mismo los cuerpos entrantes.

Apache mod_brotli y los módulos Brotli habituales para nginx solo comprimen y, por tanto, no están afectados. Envoy e Istio solo son vulnerables si está configurado el filtro de descompresión Brotli; Istio no lo activa de forma predeterminada.

Componentes afectados y versiones corregidas

ComponenteVersiones corregidasNota
libbrotli (Google Brotli)1.2.1, 1.1.1, 1.0.10están afectadas las versiones 1.0.3 a 1.2.0
Node.js26.12.1, 24.22.1, 22.23.4Versión del 21.10.2026; contiene otras correcciones (DNS, validación de nombres TLS)
Bun1.4.4reconstruir los ejecutables creados con bun build --compile
Python Brotli1.2.1urllib3, requests y aiohttp lo usan automáticamente si está instalado
Python brotlicffi1.2.1.0igual; también como extra httpx[brotli]
.NET8.0.33, 9.0.22, 10.0.14, 11 RC3actualización fuera de banda del 25.10.2026; .NET Framework no está afectado; .NET 7 no tiene corrección
Envoy1.40.0, 1.39.3, 1.38.6, 1.37.8solo con el filtro de descompresión Brotli
Istio1.31.2, 1.30.6, 1.29.9solo con el descompresor Brotli en un EnvoyFilter
Java brotli4j1.24.0el wrapper JNI incluye su propia copia de Brotli
curl/libcurlCompilado con Brotli 1.2.1solo con --compressed o CURLOPT_ACCEPT_ENCODING

Otros bindings para PHP, Ruby y Go (cgo) dependen de la libbrotli de todo el sistema o incluida. En las distribuciones Linux, Debian 12 y 13, Alpine y Amazon Linux 2023 tenían paquetes corregidos el 26 de octubre; Fedora y Red Hat estaban parcialmente corregidos, mientras que la corrección para Ubuntu y SUSE seguía pendiente.

Encontrar versiones afectadas

Para Node.js, Python y la biblioteca del sistema bastan tres consultas. En Windows, node -v ofrece el mismo resultado que en Linux.

node -v
pip show Brotli brotlicffi
pipdeptree -r -p Brotli
Opciones explicadas
OpciónEfecto
node -vmuestra la versión de la instalación activa de Node.js
pip show Brotli brotlicffimuestra la versión y los dependientes de los dos paquetes Python, si están instalados
pipdeptreelista el árbol de dependencias de los paquetes Python instalados (debe instalarse por separado)
-rinvierte el árbol: muestra qué paquetes incluyen el paquete indicado
-p Brotlilimita la salida al paquete Brotli

En Debian/Ubuntu y Alpine, el gestor de paquetes muestra la versión de la biblioteca del sistema:

dpkg -l 'libbrotli*'
apk info -v brotli-libs
Opciones explicadas
OpciónEfecto
dpkg -l 'libbrotli*'lista todos los paquetes instalados cuyo nombre comienza por libbrotli, con su versión
apk info -v brotli-libsmuestra el paquete Alpine brotli-libs con su número de versión

Las imágenes de contenedor deben revisarse por separado: un host actualizado no sirve de nada si la imagen contiene una versión antigua de Node.js o una libbrotli incluida. Después de la actualización, deben reconstruirse las imágenes y reiniciarse las cargas de trabajo en ejecución; para Bun y brotli4j esto también se aplica a las aplicaciones que vinculan Brotli estáticamente.

Runners GitHub autohospedados: setup-node toma la versión de la caché

actions/setup-node con node-version: 22 no comprueba de forma predeterminada si existe una versión 22 más reciente. Si ya hay una versión adecuada en la caché de herramientas del runner, se utiliza esa. En los runners alojados por GitHub, la imagen se despliega regularmente de nuevo; en cambio, un runner autohospedado conserva su caché hasta que alguien la vacía. En el registro aparece, por ejemplo, Found in cache @ .../_tool/node/22.23.1/x64.

La solución consiste en añadir una línea en cada paso setup-node:

- uses: actions/setup-node@v4
  with:
    node-version: 22
    check-latest: true
Opciones explicadas
OpciónEfecto
node-version: 22selecciona la versión más reciente disponible de la línea 22.x
check-latest: trueconsulta el directorio de versiones de Node.js en cada ejecución y descarga una versión más reciente, en lugar de usar la versión de la caché de herramientas

Como alternativa, se puede fijar la versión mínima (node-version: 22.23.4); entonces debe actualizarse con cada versión de seguridad. Esto es especialmente relevante para canalizaciones que obtienen contenido de servidores externos, como escáneres, verificadores de enlaces o feeds: allí fetch() se ejecuta contra servidores que usted no controla y el runner suele tener acceso a secretos de despliegue.

Si no es posible actualizar de inmediato

Las mitigaciones actúan sobre la decodificación:

  • Entrante: Rechace en el proxy inverso o middleware las solicitudes con Content-Encoding que contengan br. La comparación debe ignorar mayúsculas y minúsculas y también cubrir listas como gzip, br.
  • Saliente: Elimine br de Accept-Encoding y descarte las respuestas con Content-Encoding: br antes de decodificarlas. Eliminarlo únicamente de Accept-Encoding no basta, porque un servidor manipulado puede enviar la codificación de todos modos. Con el fetch() integrado de Node.js y Bun no es posible; en ese caso solo sirve actualizar.
  • curl: No utilice --compressed; en libcurl, mantenga CURLOPT_ACCEPT_ENCODING en NULL.
  • Python: Desinstale Brotli y brotlicffi, y elimine de las dependencias extras como httpx[brotli]. urllib3, requests y aiohttp volverán entonces a gzip y deflate.
  • Envoy/Istio: Elimine el descompresor Brotli de la configuración o de los EnvoyFilters y compruebe la configuración en ejecución.

Cloudflare Workers y navegadores

Quien opera aplicaciones como Cloudflare Worker no ejecuta un proceso propio de Node.js; el runtime workerd lo opera y actualiza Cloudflare. El 26 de octubre aún no había una declaración de Cloudflare sobre CVE-2026-111497; los clientes no pueden cambiar nada en el propio runtime. Sin embargo, las herramientas relacionadas con el Worker siguen afectadas: los scripts de compilación, wrangler y los entornos de desarrollo locales se ejecutan sobre Node.js y deberían usar una versión corregida. Los navegadores utilizan sus propias implementaciones de Brotli; en los avisos de los fabricantes y de los investigadores de seguridad no se mencionan como afectados.

Cronología

FechaEvento
Febrero de 2026OpenAI Codex Security comunica el error; la corrección llega al código fuente de Brotli sin publicarse en una versión
21.10.2026Node.js publica 26.12.1, 24.22.1 y 22.23.4
22.10.2026Brotli 1.2.1 y brotlicffi 1.2.1.0 en PyPI; análisis de Imperva con ejecución de código
23.10.2026Correcciones para libbrotli, Bun, Envoy e Istio
24.10.2026brotli4j 1.24.0, paquetes para Amazon Linux 2023
25.10.2026Actualizaciones fuera de banda para .NET
26.10.2026Debian y Alpine corregidos; Fedora y Red Hat parcialmente

Fuentes

  1. Node.js: October 2026 Security Releases

    aviso oficial con la causa, las líneas afectadas y las versiones corregidas, así como otros nueve CVE de la misma versión.

    https://nodejs.org/en/blog/vulnerability/october-2026-security-releases
  2. NVD: CVE-2026-111497

    entrada CVE con puntuación CVSS 4.0 de 9.2.

    https://nvd.nist.gov/vuln/detail/cve-2026-111497
  3. Imperva: Node2Shell, from Brotli data to remote code execution

    análisis técnico con demostración de ejecución de código, ruta de cliente y servidor en Node.js, y versiones afectadas de Express y body-parser.

    https://www.imperva.com/blog/node2shell-from-brotli-data-to-remote-code-execution/
  4. Aikido: Python packages vulnerable to Node2Shell

    causa en DecodeBlockTypeAndLength(), versiones corregidas en todos los ecosistemas, cronología y mitigaciones; actualizado continuamente.

    https://www.aikido.dev/blog/python-packages-vulnerable-node2shell-brotli-cve-2026-111497
  5. Microsoft .NET Blog: .NET October 2026 out-of-band security updates

    versiones fuera de banda para las versiones compatibles de .NET.

    https://devblogs.microsoft.com/dotnet/dotnet-october-2026-oob-security-updates/
  6. Broccoli2Shell

    página informativa sobre la vulnerabilidad bajo su segundo nombre.

    https://broccoli2shell.com/
  7. heise online: Vulnerabilidad en el decodificador Brotli no solo en Node.js, sino también en Bun, Python y más
  8. actions/setup-node: check-latest

    documentación de la opción que comprueba la caché de herramientas frente al directorio de versiones en cada ejecución.

    https://github.com/actions/setup-node#check-latest-version

Comentarios

Los comentarios se cargan desde GitHub / Giscus.