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. Elfetch()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.jsbody-parser2.0.0 a 2.3.0 y Express 5.0.0 a 5.3.0 con los analizadores configuradosjson()oraw(). Un servidorhttpbá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
| Componente | Versiones corregidas | Nota |
|---|---|---|
| libbrotli (Google Brotli) | 1.2.1, 1.1.1, 1.0.10 | están afectadas las versiones 1.0.3 a 1.2.0 |
| Node.js | 26.12.1, 24.22.1, 22.23.4 | Versión del 21.10.2026; contiene otras correcciones (DNS, validación de nombres TLS) |
| Bun | 1.4.4 | reconstruir los ejecutables creados con bun build --compile |
Python Brotli | 1.2.1 | urllib3, requests y aiohttp lo usan automáticamente si está instalado |
Python brotlicffi | 1.2.1.0 | igual; también como extra httpx[brotli] |
| .NET | 8.0.33, 9.0.22, 10.0.14, 11 RC3 | actualización fuera de banda del 25.10.2026; .NET Framework no está afectado; .NET 7 no tiene corrección |
| Envoy | 1.40.0, 1.39.3, 1.38.6, 1.37.8 | solo con el filtro de descompresión Brotli |
| Istio | 1.31.2, 1.30.6, 1.29.9 | solo con el descompresor Brotli en un EnvoyFilter |
| Java brotli4j | 1.24.0 | el wrapper JNI incluye su propia copia de Brotli |
| curl/libcurl | Compilado con Brotli 1.2.1 | solo 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
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
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
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-Encodingque contenganbr. La comparación debe ignorar mayúsculas y minúsculas y también cubrir listas comogzip, br. - Saliente: Elimine
brdeAccept-Encodingy descarte las respuestas conContent-Encoding: brantes de decodificarlas. Eliminarlo únicamente deAccept-Encodingno basta, porque un servidor manipulado puede enviar la codificación de todos modos. Con elfetch()integrado de Node.js y Bun no es posible; en ese caso solo sirve actualizar. - curl: No utilice
--compressed; en libcurl, mantengaCURLOPT_ACCEPT_ENCODINGenNULL. - Python: Desinstale
Brotliybrotlicffi, y elimine de las dependencias extras comohttpx[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
| Fecha | Evento |
|---|---|
| Febrero de 2026 | OpenAI Codex Security comunica el error; la corrección llega al código fuente de Brotli sin publicarse en una versión |
| 21.10.2026 | Node.js publica 26.12.1, 24.22.1 y 22.23.4 |
| 22.10.2026 | Brotli 1.2.1 y brotlicffi 1.2.1.0 en PyPI; análisis de Imperva con ejecución de código |
| 23.10.2026 | Correcciones para libbrotli, Bun, Envoy e Istio |
| 24.10.2026 | brotli4j 1.24.0, paquetes para Amazon Linux 2023 |
| 25.10.2026 | Actualizaciones fuera de banda para .NET |
| 26.10.2026 | Debian y Alpine corregidos; Fedora y Red Hat parcialmente |
Comentarios
Los comentarios se cargan desde GitHub / Giscus.