CVE-2026-111497, el fallo del decodificador Brotli que Node.js corrigió el 21 de octubre, entró el 27 de octubre al catálogo de vulnerabilidades explotadas conocidas (KEV) de CISA, después de pruebas de concepto públicas, dos demostraciones independientes de ejecución de código y tráfico de explotación real. Además dejó de ser un tema de Node.js: el fallo vive en la biblioteca Brotli de Google, así que también lo traen paquetes de Python, .NET, Bun, Envoy e Istio, y Node.js 20, 23 y 25 nunca van a recibir arreglo.
En mi resumen del día de seguridad del 21 de octubre puse a Node.js en ‘48 h (hoy si descomprimís Brotli no confiable)’. Una semana después, esa evaluación quedó vieja. Este post cubre qué cambió, qué implica para equipos que publican código y el trabajo de esta semana: un inventario de solo lectura, pasos de parcheo por entorno y mitigaciones que aguantan hasta que puedas parchear. Cada versión y comando sale de advisories de los proveedores, de la documentación de los proyectos o de mis propias revisiones de código fuente y registros del 28 de octubre.
1. Contexto: De una Línea en el Aviso de Node.js a una Entrada en el KEV
El advisory de Node.js describe el fallo sin vueltas: un cambio de bloque inválido se reportaba como una necesidad temporal de más datos en lugar de un error de formato permanente, así que el decodificador en streaming seguía agregando bytes a un búfer interno de ocho bytes. Cualquiera que logre que tu proceso descomprima datos Brotli manipulados puede corromper su memoria, con resultados que van desde una caída hasta la exposición de memoria del proceso o la ejecución remota de código. Node lo califica como High y acredita el reporte a OpenAI Codex Security (Khai Tran y Sylvie Mayer). Google, como CNA, le da CVSS v4.0 9.2 Critical en el registro del CVE, que cubre Brotli 1.0.3 a 1.2.0 en todas las plataformas.
Lo que cambió después del 21 de octubre es el panorama de amenazas. CISA lo agregó al catálogo KEV el 27 de octubre como ‘Google Brotli Unchecked Return Value Vulnerability’, con fecha límite el 10 de noviembre para las agencias federales de EE. UU. El día anterior, ELLIO registró una única petición de explotación contra Node.js 24.22.0 en x86-64, desde una IP que ya había visto lanzando exploits de PHP2Shell. En el camino el fallo juntó nombres: Node2Shell, Brotli2Shell, HTTP2Shell y Broccoli2Shell son el mismo CVE.
Cronología (fechas tal como las publica cada fuente)
Cómo lo califica cada fuente
| Fuente | Calificación | Cómo leerla |
|---|---|---|
| Google (CNA, registro del CVE) | CVSS v4.0 9.2, Critical | AT:P: el ataque necesita una condición previa, un camino que decodifique Brotli no confiable |
| Node.js | High | Sin CVSS en el advisory y sin workaround |
| Microsoft (.NET) | CVSS v3.1 8.1 | AC:H; .NET solo queda expuesto si la app activa la descompresión Brotli |
| Red Hat | Important, CVSS v3.1 8.1 | RHSB-2026-015 lista RHEL 7 a 10; las erratas seguían en curso el 27 de octubre |
| Ubuntu | Prioridad Medium | Sus paquetes nodejs usan la libbrotli del sistema y figuran como no afectados |
| CISA KEV | Agregado el 27 oct, límite el 10 nov | Figura como explotado; uso en ransomware ‘Unknown’ |
El arreglo fue público durante ocho meses
El commit upstream entró el 27 de febrero con un mensaje de una línea que no dice nada de seguridad, y quedó en un repositorio público hasta las versiones del 21 de octubre. Cualquiera que comparara decode.c podía encontrarlo. Node.js parcheó su copia incluida sin pasar a una versión nueva de Brotli, y eso importa a la hora de verificar el arreglo (paso 1, más abajo).
Dónde estamos (revisado el 28 de octubre de 2026)
Versiones corregidas
Las versiones de Node.js, Brotli, Python, .NET y Bun salen de nodejs.org, el registro del CVE, PyPI, el advisory de Microsoft y la release de Bun. Los tags del código fuente de Node.js los revisé yo.
Inclusión en el KEV
La entrada del catálogo de CISA, que leí en su feed JSON: agregada el 27 de octubre, límite el 10 de noviembre, CWE-252 y CWE-787.
Explotación real
ELLIO reporta una petición de explotación desde 94.154.43.7 el 26 de octubre; Tenable dice que no lo confirmó de forma independiente, y las pruebas de ELLIO con esa cadena dieron cero shells en 50 intentos. CISA no publica su evidencia. No encontré ningún compromiso exitoso confirmado, lo que es ausencia de evidencia, no evidencia de ausencia.
Ejecución de código
Demostrada solo en laboratorio: Imperva en arm64 tras varios intentos, ELLIO en x86-64 hacia el quinto intento con ASLR activo. Las dos cadenas dependen de builds exactos.
Arreglos que todavía faltan
Al 26 de octubre, Tenable no lista versiones corregidas de ClickHouse, Apache Arrow ni FFmpeg. El tracker de Debian sigue marcando vulnerables sus paquetes nodejs en bookworm y trixie, y las erratas de Red Hat están pendientes.
Regla de oro
Contá decodificadores Brotli, no instalaciones de Node.js: parcheá cada runtime y paquete que decodifique datos br no confiables, reiniciá lo que los cargó y verificá por versión o revisión de paquete, nunca por process.versions.brotli.
2. Cinco Implicaciones para Equipos que Publican Código
El FAQ de Tenable es el mejor mapa del alcance en un solo lugar, y el análisis de Imperva es la explicación más clara de qué caminos de una aplicación llegan de verdad al decodificador. Leídos juntos, cambian cómo priorizaría este fallo.
La ventana de 48 horas ahora es una fecha límite del KEV
CISA KEV · Rapid7 · ELLIO
Rapid7 señala que CISA lo incluyó por evidencia de explotación activa. Las agencias federales tienen hasta el 10 de noviembre; para todos los demás, leelo como ‘esta semana’. Para cualquier servicio expuesto a internet que decodifique Brotli en cualquier dirección, mi urgencia pasa de 48 horas a hoy.
Los exploits dependen del build, y eso corta para los dos lados
Imperva · ELLIO
ELLIO dice que la cadena observada apunta a un único binario, la release oficial v24.22.0 para x86-64. Eso hace probable que los intentos fallen, pero ELLIO espera oleadas, porque el atacante mide los offsets una vez por build y los reutiliza en cada host que lo corre. Los intentos fallidos igual tiran abajo el worker, y ELLIO advierte que los core dumps pueden exponer datos de sesión.
Es un fallo de biblioteca: contá decodificadores, no runtimes
Tenable · registro del CVE · Red Hat
El registro del CVE cubre a Brotli, no a Node.js. Tenable lista Brotli y brotlicffi de Python, .NET 8 a 11, Bun, Envoy, Istio, los builds de PHP para Windows y la extensión brotli de PHP, y Red Hat suma Firefox y Thunderbird, que traen su propia copia. Actualizar Node.js arregla Node.js y nada más.
Cuentan las dos direcciones
Imperva · Akamai · Aikido
Hacia adentro, Express 5 y body-parser 2 descomprimen por defecto los cuerpos de petición Brotli, así que cualquier cliente puede entregar el payload. Hacia afuera, el fetch() de Node, axios y got decodifican lo que mande el servidor, así que un webhook, una vista previa de enlaces o un crawler que llama a una URL que no controlás es un blanco. Un servidor node:http pelado no decodifica cuerpos por sí solo.
Las líneas fuera de soporte quedan a su suerte
HeroDevs · Node.js · .NET
Node.js 20, 23 y 25 no reciben arreglo: HeroDevs leyó el código de la última 20.20.2 y encontró el decodificador vulnerable (Brotli 1.1.0), con fetch() decodificando br también ahí. Los paquetes nodejs del propio Debian (18.x en bookworm, 20.x en trixie) seguían marcados como vulnerables cuando revisé. Y .NET 8 y 9 se quedan sin soporte el 10 de noviembre, el mismo día de la fecha límite del KEV.
Más allá de Node.js: versiones corregidas y cuándo estás expuesto
| Producto | Corregido en | Expuesto cuando |
|---|---|---|
| Google Brotli (biblioteca C) | 1.0.10 · 1.1.1 · 1.2.1 | Cualquier cosa que decodifique br no confiable con 1.0.3 a 1.2.0 |
| Node.js | 22.23.4 · 24.22.1 · 26.12.1 | Brotli no confiable llega a node:zlib: parsers de cuerpos, fetch(), tus propias llamadas |
| Python Brotli / brotlicffi | 1.2.1 / 1.2.1.0 | Instalados junto a urllib3/requests, httpx[brotli] o aiohttp |
| .NET 8 / 9 / 10 / 11 | 8.0.33 · 9.0.22 · 10.0.14 · 11 RC3 | Solo si una app activa la descompresión Brotli de peticiones o respuestas, o llama a BrotliStream o BrotliDecoder |
| Bun | 1.4.4 | Versiones 1.0.21 a 1.4.3, según Tenable |
| Envoy / Istio | Envoy 1.36.12, 1.37.8, 1.38.6, 1.39.3, 1.40.0 · Istio 1.29.9, 1.30.6, 1.31.2 | Solo con un descompresor Brotli configurado |
| PHP en Windows | 8.2.35-1 · 8.3.36-1 · 8.4.27-1 · 8.5.12-1 | Con la descompresión automática de cURL activada (viene desactivada) |
| FFmpeg · ClickHouse · Apache Arrow | Sin versión corregida listada al 26 oct | JFrog, vía Tenable: control del puntero de instrucción (FFmpeg vía libjxl), caída del servidor (ClickHouse), DoS (Arrow) |
Por dónde llega Brotli no confiable al decodificador en una app Node.js
| Camino | Cuándo decodifica | Si hoy no podés parchear |
|---|---|---|
| Express 5 / body-parser 2 (json, raw, text, urlencoded) | Por defecto: inflate es true | inflate: false, o rechazá br antes de los parsers o en el proxy |
| Koa con @koa/bodyparser | ELLIO lo lista entre sus objetivos que funcionaron | Rechazá br en el proxy |
| Servidor node:http pelado | Nunca por sí solo | Buscá llamadas Brotli de zlib en tus handlers |
| fetch() integrado | Lo que indique el Content-Encoding de la respuesta | Parcheá; restringí la salida para URLs que manda el usuario |
| axios, got | decompress es true por defecto | decompress: false para URLs que no controlás |
| Tus propias llamadas a node:zlib | zlib.brotliDecompress(), createBrotliDecompress() | Dejá de pasarles datos no confiables (consejo de Red Hat) |
Express 4 usa body-parser 1.x, que solo descomprime gzip y deflate; el soporte de Brotli llegó en body-parser 2.0.0. Ya que estás, body-parser 2.4.0 y 1.20.9 (22 de octubre) también corrigen CVE-2026-111181, una caída distinta que provoca una sola petición con cuerpo comprimido.
3. Qué Hacer Esta Semana
El mismo orden que con cualquier fallo de runtime: encontrá cada copia, parcheala como pide cada entorno, reiniciá lo que la cargó y poné una mitigación delante de lo que hoy no podés parchear. Todo lo del paso 1 solo lee.
Paso 1: Encontrá cada decodificador
Runtimes de Node.js: hosts, contenedores, ejecutables únicos, tu código
Comandos para Linux; en macOS sacá el -r de xargs. Corrélos en hosts, dentro de imágenes y en runners de CI. La cadena del fusible SEA sale de la documentación de Node.js, y el grep de la URL de release funciona con builds oficiales de nodejs.org; lo probé contra mi propio binario.
# 1. Cada binario node del host, gestores de versiones incluidos
find / -xdev -type f -name node -perm -u+x 2>/dev/null | while read -r b; do
echo "$("$b" -v 2>/dev/null) $b"
done | sort
# corregidas: v22.23.4, v24.22.1, v26.12.1 · v20, v23, v25: sin arreglo
# 2. Contenedores en marcha: lo desplegado, no a dónde apunta hoy el tag
docker ps --format '{{.Names}}' | while read -r c; do
echo "$c $(docker exec "$c" node -v 2>/dev/null || echo 'no node')"
done
grep -rn --include='Dockerfile*' 'FROM node:' .
# 3. Ejecutables únicos (SEA): el fusible termina en :1 cuando hay un blob inyectado
find /opt /usr/local -xdev -type f -perm -u+x -size +40M -print0 2>/dev/null \
| xargs -0 -r grep -l 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2:1'
# los builds oficiales de nodejs.org, y los SEA hechos con ellos, llevan su URL de release
grep -aoE 'download/release/v[0-9]+\.[0-9]+\.[0-9]+/' ./my-sea-app | sort -u
# 4. Las apps Electron traen su propio Node: buscá Electron 45.1.0,
# 44.10.0 o 43.8.4 (Node.js 24.22.1) en las notas de cada proveedor
# 5. Tu código: llamadas directas al decodificador Brotli
grep -rnE 'createBrotliDecompress|brotliDecompress(Sync)?\(' src/ \
--include='*.js' --include='*.mjs' --include='*.cjs' --include='*.ts'Las otras copias: Python, la biblioteca del sistema, .NET, Bun
Los comandos de pip salen del análisis de Aikido. Compará las revisiones de paquete de tu distro con USN-8956-1, DSA-6582-1, DLA-4855-1 o el aviso de tu proveedor, no con los números upstream.
# Python: Brotli y brotlicffi compilan su propia copia del decodificador
pip show Brotli brotlicffi # corregidas: 1.2.1 / 1.2.1.0
docker run --rm <image> pip show Brotli brotlicffi
grep -i brotli poetry.lock uv.lock requirements*.txt
# La biblioteca del sistema (los paquetes nodejs de Ubuntu y Alpine la usan)
dpkg -l 'libbrotli*' | awk '/^ii/ {print $2, $3}' # Debian/Ubuntu
apk info -v 2>/dev/null | grep brotli # Alpine: brotli-libs
rpm -q brotli # familia RHEL
# .NET y Bun
dotnet --list-runtimes # corregidas: 8.0.33, 9.0.22, 10.0.14, 11.0.0-rc.3
bun --version # corregida: 1.4.4
# Node: la respuesta es process.version, no process.versions.brotli
node -p "process.version + ' brotli ' + process.versions.brotli"No verifiques con process.versions.brotli
Revisé el código fuente de Node.js en cada tag de release. La 22.23.4 corregida sigue declarando Brotli 1.1.0, y la 24.22.1 y la 26.12.1 siguen declarando 1.2.0, porque Node parcheó decode.c sin cambiar la versión; process.versions.brotli lee ese número, así que es idéntico antes y después del arreglo. Mi propia laptop responde v22.22.0 y brotli 1.1.0: vulnerable, y el campo brotli diría lo mismo después de actualizar. Juzgá Node por process.version y la biblioteca del sistema por su revisión de paquete.
Paso 2: Parcheá según el entorno
Un arreglo en disco no hace nada por un proceso que cargó el código viejo, así que cada tarjeta de abajo termina en un reinicio, un rebuild o un redeploy.
Node.js en hosts y gestores de versiones
nodejs.org · 21 oct
Instalá 22.23.4, 24.22.1 o 26.12.1, o una posterior en cada línea, y después reiniciá todos los procesos: unidades de systemd, pm2, Supervisor, tareas de cron. HeroDevs aclara que actualizar el paquete brotli de npm no cambia nada, porque el fallo vive en el binario del runtime.
nvm install 24.22.1 && nvm alias default 24.22.1 volta install node@24.22.1 node -v # v24.22.1 o posterior sudo systemctl restart my-node-app # cada servicio, worker y tarea
Imágenes de Docker
Reconstruí, no reinicies · fijá tag + digest
Los tags oficiales corregidos están en Docker Hub (node:22.23.4, node:24.22.1, node:26.12.1 y sus variantes -slim y -alpine), y los tags base se volvieron a publicar el 28 de octubre. node:20.20.2 se publicó por última vez el 22 de abril y no va a cambiar. Fijá el tag y su digest, reconstruí sin caché y recreá los contenedores.
docker buildx imagetools inspect node:24.22.1-slim | grep -m1 Digest # FROM node:24.22.1-slim@sha256:<digest> docker compose build --pull --no-cache docker compose up -d --force-recreate docker compose exec app node -v
Paquetes de distribución
USN-8956-1 · DSA-6582-1 · DLA-4855-1 · RHSB-2026-015
El nodejs de Ubuntu usa la biblioteca del sistema, así que Ubuntu lo marca como no afectado y el arreglo es libbrotli (1.2.0-3ubuntu0.1 en 26.04, 1.1.0-2ubuntu0.1 en 24.04, 1.0.9-2ubuntu0.1 en 22.04). Debian corrigió brotli en trixie (1.1.0-2+deb13u1) y bookworm (1.0.9-2+deb12u1), pero sigue listando su nodejs como vulnerable ahí. El nodejs y el nodejs-current de Alpine se compilan con --shared-brotli (leí los APKBUILD), así que brotli-libs también cuenta. El boletín de Red Hat seguía ‘Ongoing’ el 27 de octubre.
sudo apt-get update && sudo apt-get install --only-upgrade libbrotli1 apk upgrade brotli-libs nodejs # Alpine, como root # Procesos que todavía mapean la biblioteca reemplazada: reinicialos sudo grep -l 'libbrotli.*(deleted)' /proc/[0-9]*/maps 2>/dev/null
Python
PyPI · 22 oct · PYSEC-2026-4322 / 4323
Brotli 1.2.1 y brotlicffi 1.2.1.0 compilan el decodificador corregido. urllib3, requests, httpx y aiohttp no son vulnerables por sí mismos; decodifican br a través de estos paquetes cuando están instalados. Regenerá los lockfiles de Poetry, uv o pip-tools y reconstruí las imágenes. Si los bindings vienen de un paquete de la distro, el arreglo llega por la distro.
pip install -U "Brotli>=1.2.1" # solo si pip show lo encontró pip install -U "brotlicffi>=1.2.1.0" # ídem pip-audit # marca PYSEC-2026-4322 / 4323
.NET
Advisory de Microsoft · fuera de ciclo, 25 oct
Instalá el runtime 8.0.33, 9.0.22, 10.0.14 u 11.0.0-rc.3 (SDK 8.0.133/8.0.427, 9.0.123/9.0.320, 10.0.114/10.0.403) y reiniciá las apps. Las apps self-contained hay que reconstruirlas y volver a desplegarlas; las NativeAOT, republicarlas con el SDK corregido, porque el runtime compartido no reemplaza un decodificador ya enlazado en el ejecutable. .NET Framework no está afectado. Si ya descomprimís Brotli y todavía no podés actualizar, Microsoft propone estos cambios, y advierte que no agregues descompresión que hoy no usás:
// Solo si YA llamás a AddRequestDecompression: sacá el proveedor br
builder.Services.AddRequestDecompression(options =>
{
options.DecompressionProviders.Remove("br");
});
// Solo si YA definís AutomaticDecompression: dejá Brotli afuera
var handler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};Bun, Envoy, Istio, Electron y el resto
Tenable · releases de Electron · php.net
Bun: 1.4.4. Envoy e Istio: las versiones corregidas de la tabla de arriba, o sacá el filtro descompresor Brotli en las dos direcciones hasta actualizar. Electron 45.1.0, 44.10.0 y 43.8.4 traen Node.js 24.22.1, pero cada app Electron necesita que su proveedor publique un rebuild; no encontré ninguna release 42.x con ese cambio. PHP en Windows: los rebuilds -1. La extensión brotli de PHP: 0.21.1, según Tenable.
bun upgrade && bun --version # 1.4.4 o posterior
Node.js 20, 23, 25 y anteriores
Sin arreglo upstream · HeroDevs
Pasá a 24 o 26: la 24 está en mantenimiento hasta abril de 2028 y la 26 pasa a LTS el 28 de octubre, según el calendario de releases de Node.js; la 22 termina en abril de 2027. HeroDevs dice que prepara builds parcheados para su Never-Ending Support pago, empezando por 20.x. Hasta que migres, cada mitigación de abajo es permanente, no temporal.
Paso 3: Mitigá lo que hoy no podés parchear
Node.js no ofrece workaround, y Rapid7 e Imperva coinciden en que el único arreglo es actualizar. Lo que sí podés hacer es mantener el Brotli no confiable lejos del decodificador, en los caminos que de verdad usás.
En el borde: rechazá cuerpos de petición codificados con Brotli
El boletín de Red Hat recomienda quitar o rechazar Content-Encoding: br de clientes no confiables en el proxy o el balanceador. Rechazar es más limpio: si solo quitás la cabecera, la app recibe bytes comprimidos que no puede parsear. $http_content_encoding es la variable estándar de nginx para esa cabecera de petición.
# nginx, dentro de server {}: rechazá cuerpos de petición codificados con Brotli
if ($http_content_encoding ~* br) {
return 415;
}
# Envoy / Istio: si configuraste un descompresor Brotli, sacalo
# en las dos direcciones hasta correr una versión corregida (Tenable)En la app: Express hacia adentro; fetch, axios y got hacia afuera
inflate es una opción documentada de body-parser (los cuerpos rechazados reciben un 415), y decompress está documentada en axios y en got; el middleware que rechaza solo Brotli es mío. El fetch() integrado de Node no tiene un interruptor para desactivar la decodificación: leí el código de fetch de undici, y solo agrega su Accept-Encoding por defecto si no definiste uno.
// Express 5 / body-parser 2: rechazá todo cuerpo comprimido (igual para raw, text, urlencoded)
app.use(express.json({ inflate: false }));
// ...o rechazá solo Brotli, antes de cualquier parser, y mantené gzip y deflate
app.use((req, res, next) => {
if (/\bbr\b/i.test(req.headers['content-encoding'] || '')) return res.sendStatus(415);
next();
});
// Hacia afuera: dejá de pedir br (solo sirve con servidores honestos)
const response = await fetch(url, { headers: { 'accept-encoding': 'gzip, deflate' } });
// axios y got: sin decodificación automática para URLs que no controlás
await axios.get(url, { decompress: false });
await got(url, { decompress: false });Qué cubren estas mitigaciones y qué no
- Las reglas en el borde solo protegen la entrada: no hacen nada por las respuestas que tus servicios piden a servidores que controla un atacante (Tenable, Aikido).
- Accept-Encoding no es un control: un servidor hostil puede mandar br igual. El fetch de undici, como urllib3, elige el decodificador según la cabecera Content-Encoding de la respuesta, no según lo que pediste.
- Python: desinstalar Brotli y brotlicffi saca el decodificador de urllib3, requests y aiohttp; los servidores que insisten con br pueden fallar después (Aikido). Quitá también extras como httpx[brotli].
- Envoy e Istio: desactivá el filtro descompresor Brotli en las dos direcciones si configuraste uno (Tenable).
- Salida: Akamai sugiere segmentar: restringí a qué hosts pueden llegar los servicios vulnerables, lo que achica el camino de fetch() con URLs que manda el usuario.
Las señales son débiles; las caídas, no
Imperva dice que las salidas inesperadas de procesos durante la descompresión y los errores del decodificador ayudan a priorizar, pero ninguno es por sí solo una señal fiable de explotación. Tomá las caídas repetidas de workers en endpoints que aceptan cuerpos comprimidos como algo para investigar, y seguí el consejo de ELLIO de restringir el acceso a los core dumps y cuánto tiempo los guardás. ELLIO publicó una IP de origen y un hash del payload; una coincidencia implica aislar el host, no solo bloquear la dirección.
El orden en que yo trabajaría
- 1. Hoy: servicios expuestos a internet que descomprimen cuerpos de petición (Express 5, body-parser 2, Koa) o piden URLs que manda el usuario (webhooks, vistas previas de enlaces, crawlers). Parchealos, o poné ya delante las mitigaciones del borde y de la app.
- 2. También hoy: reconstruí cada imagen fijada a un tag de node anterior y reiniciá cada proceso de larga duración.
- 3. Antes del viernes 30 de octubre: Brotli y brotlicffi de Python, la libbrotli del sistema, Bun, Envoy e Istio, y las apps .NET que activaron la descompresión Brotli.
- 4. Antes del 10 de noviembre: un plan con fecha para salir de Node.js 20, 23 y 25, y de .NET 8 y 9.
- 5. Cada pocos días: volvé a revisar ClickHouse, Apache Arrow, FFmpeg, el nodejs de Debian, las erratas de Red Hat y las apps Electron que usás.
Conclusión
Hace una semana, CVE-2026-111497 era la primera línea de una actualización de seguridad de Node.js. Hoy es una entrada del KEV con exploits públicos, y la unidad real de exposición es el decodificador Brotli, esté donde esté: Node.js, un wheel de Python, una app .NET que lo activó, un filtro de Envoy, una app Electron.
La buena noticia es que la exposición necesita un camino: el Brotli no confiable tiene que llegar a un decodificador. Parcheá hoy los caminos expuestos a internet, reconstruí y reiniciá para que el parche sea real, poné una mitigación delante de lo que no podés parchear y usá la fecha del 10 de noviembre para jubilar Node.js 20 y .NET 8 y 9.
Esta semana en una pantalla
Revisar
- • node -v en todos lados, no process.versions.brotli
- • pip show Brotli brotlicffi
- • dotnet --list-runtimes, bun --version
Parchear
- • Node 22.23.4 / 24.22.1 / 26.12.1
- • libbrotli, Brotli 1.2.1, .NET fuera de ciclo
- • Reconstruir imágenes, reiniciar procesos
Vigilar
- • Cuerpos br en el borde
- • fetch() a URLs que no controlás
- • Plan de fin de soporte antes del 10 nov
Fuentes
- Node.js — Actualizaciones de seguridad de octubre de 2026 (CVE-2026-111497)
- CVE.org — Registro de CVE-2026-111497 (Google como CNA, CVSS v4.0 9.2)
- Google Brotli — Release v1.2.1 (también 1.1.1 y 1.0.10)
- CISA — Agrega dos vulnerabilidades explotadas conocidas al catálogo (27 oct)
- Tenable — Brotli2Shell: preguntas frecuentes sobre CVE-2026-111497
- Imperva — Node2Shell: de datos Brotli a ejecución remota de código
- ELLIO — Node2Shell: RCE en builds estándar de Node.js
- Akamai — Dentro de Node2Shell: una mirada de cerca a CVE-2026-111497
- Rapid7 — ETR: CVE-2026-111497, escritura fuera de límites en el decodificador Brotli de Node.js
- HeroDevs — CVE-2026-111497 en Node.js fuera de soporte
- Aikido — Paquetes de Python vulnerables a Node2Shell
- Microsoft — Advisory de seguridad de .NET para CVE-2026-111497
- Red Hat — RHSB-2026-015, decodificador Brotli de Google (node2shell)
- Ubuntu — CVE-2026-111497
- Debian security tracker — CVE-2026-111497
- body-parser — GHSA-27r3-jxmh-p828 (CVE-2026-111181)
- Help Net Security — Node2Shell / Broccoli2Shell (27 oct)



