SeguridadNode.js

Node2Shell (CVE-2026-111497): Explotado, en el KEV de CISA y Más Allá de Node.js

28 de octubre de 2026
13 min de lectura
Una prensa hidráulica comprime un cubo de vidrio transparente que se agrieta con fisuras naranjas luminosas en un taller en penumbra
Compartir:

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)

27 febGoogle sube el arreglo a google/brotli como 0ed4268a, ‘Detect and report invalid stream earlier.’ Sin versión ni advisory.
Inicios octEnvoy e Istio publican arreglos sin nombrar el fallo (Tenable).
21 octNode.js 22.23.4, 24.22.1 y 26.12.1. Google etiqueta Brotli 1.0.10, 1.1.1 y 1.2.1, cada una con CVE-2026-111497 en su sección SECURITY.
22 octGoogle publica el registro del CVE. Brotli 1.2.1 y brotlicffi 1.2.1.0 llegan a PyPI, Bun publica la 1.4.4 y aparece en GitHub la primera prueba de concepto pública (HeroDevs). Imperva muestra ejecución de código sobre la imagen oficial de Node.js 24.22.0 linux arm64.
25 octMicrosoft publica actualizaciones fuera de ciclo de .NET 8.0.33, 9.0.22, 10.0.14 y 11 RC3.
26 octELLIO registra tráfico de explotación a las 15:08 UTC. Ubuntu publica USN-8956-1 para libbrotli, Red Hat abre RHSB-2026-015 y PHP reconstruye sus paquetes de Windows con Brotli 1.2.1.
27 octCISA agrega el CVE al KEV. Electron 45.1.0, 44.10.0 y 43.8.4 pasan a Node.js 24.22.1.

Cómo lo califica cada fuente

FuenteCalificaciónCómo leerla
Google (CNA, registro del CVE)CVSS v4.0 9.2, CriticalAT:P: el ataque necesita una condición previa, un camino que decodifique Brotli no confiable
Node.jsHighSin CVSS en el advisory y sin workaround
Microsoft (.NET)CVSS v3.1 8.1AC:H; .NET solo queda expuesto si la app activa la descompresión Brotli
Red HatImportant, CVSS v3.1 8.1RHSB-2026-015 lista RHEL 7 a 10; las erratas seguían en curso el 27 de octubre
UbuntuPrioridad MediumSus paquetes nodejs usan la libbrotli del sistema y figuran como no afectados
CISA KEVAgregado el 27 oct, límite el 10 novFigura 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

ProductoCorregido enExpuesto cuando
Google Brotli (biblioteca C)1.0.10 · 1.1.1 · 1.2.1Cualquier cosa que decodifique br no confiable con 1.0.3 a 1.2.0
Node.js22.23.4 · 24.22.1 · 26.12.1Brotli no confiable llega a node:zlib: parsers de cuerpos, fetch(), tus propias llamadas
Python Brotli / brotlicffi1.2.1 / 1.2.1.0Instalados junto a urllib3/requests, httpx[brotli] o aiohttp
.NET 8 / 9 / 10 / 118.0.33 · 9.0.22 · 10.0.14 · 11 RC3Solo si una app activa la descompresión Brotli de peticiones o respuestas, o llama a BrotliStream o BrotliDecoder
Bun1.4.4Versiones 1.0.21 a 1.4.3, según Tenable
Envoy / IstioEnvoy 1.36.12, 1.37.8, 1.38.6, 1.39.3, 1.40.0 · Istio 1.29.9, 1.30.6, 1.31.2Solo con un descompresor Brotli configurado
PHP en Windows8.2.35-1 · 8.3.36-1 · 8.4.27-1 · 8.5.12-1Con la descompresión automática de cURL activada (viene desactivada)
FFmpeg · ClickHouse · Apache ArrowSin versión corregida listada al 26 octJFrog, 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

CaminoCuándo decodificaSi hoy no podés parchear
Express 5 / body-parser 2 (json, raw, text, urlencoded)Por defecto: inflate es trueinflate: false, o rechazá br antes de los parsers o en el proxy
Koa con @koa/bodyparserELLIO lo lista entre sus objetivos que funcionaronRechazá br en el proxy
Servidor node:http peladoNunca por sí soloBuscá llamadas Brotli de zlib en tus handlers
fetch() integradoLo que indique el Content-Encoding de la respuestaParcheá; restringí la salida para URLs que manda el usuario
axios, gotdecompress es true por defectodecompress: false para URLs que no controlás
Tus propias llamadas a node:zlibzlib.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. 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. 2. También hoy: reconstruí cada imagen fijada a un tag de node anterior y reiniciá cada proceso de larga duración.
  3. 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. 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. 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

Diego Rodriguez

Diego Rodriguez

Ingeniero Senior Full-Stack & AI

Diego tiene mas de 9 anos de experiencia construyendo aplicaciones potenciadas por IA de produccion, desde orquestacion de LLMs y pipelines RAG hasta deteccion de riesgos con ML y sistemas de trading algoritmico.

Conoce mas sobre Diego →