Node2Shell ya es HTTP2Shell: el agujero de Brotli que estuvo ocho meses arreglado y no salió en ninguna release

Node2Shell ya es HTTP2Shell: el agujero de Brotli que estuvo ocho meses arreglado y no salió en ninguna release

Escucha este artículo en audio (2:00 min, resumen del artículo original)

📻 Versión en audio: si prefieres escuchar en vez de leer, el resumen del artículo está justo aquí arriba.

Node2Shell ya es HTTP2Shell: el agujero de Brotli que estuvo ocho meses arreglado y no salió en ninguna release

El miércoles 21 de octubre, Node.js publicó una alerta con nombre de película: node2shell. Un atacante remoto, sin autenticación, podía mandar un flujo de datos comprimido con Brotli y filtrar memoria, derribar el proceso o, en el peor caso, ejecutar código. El CVE-2026-111497 es un out-of-bounds write en el decodificador de Brotli, la librería de compresión de Google, con CVSS v4.0 de 9.2 y versiones afectadas desde la 1.0.3 hasta la 1.2.0 en todas las plataformas. Un día después Python confirmó lo mismo en sus paquetes, y para el viernes ya había parches en camino para curl, Envoy, Istio y Bun. Node2Shell dejó de ser un problema de Node para convertirse en HTTP2Shell.

Por qué te alcanza aunque no uses Node

Tu entorno Python probablemente tenga dos paquetes, Brotli y brotlicffi, que compilan el mismo decodificador vulnerable. Solo el primero lleva 82,8 millones de descargas al mes en PyPI. Lo insidioso: el paquete compila directamente la librería de Brotli y clientes como httpx lo cargan automáticamente si está instalado. Tu aplicación puede estar expuesta sin importar Brotli ni una sola vez: es una dependencia transitiva de esas que nadie revisa, y el atacante la alcanza igual, ya sea con un cuerpo de petición comprimido que le mandas a tu servidor o con una respuesta comprimida de un servidor malicioso.

Peor aún: al 23 de octubre ni pip-audit, ni Dependabot ni Safety marcaban estas versiones, porque ninguna base de datos de advisories había mapeado aún el CVE a los paquetes de PyPI. La automatización te da una falsa sensación de seguridad justo cuando menos puedes confiarte.

Lo del calendario es lo escandaloso

Quien encontró el bug primero fue OpenAI, en febrero de 2026, y lo reportó como ejecución remota no autenticada que funciona en ambas direcciones. El arreglo entró al código fuente de Brotli en febrero. Pero nadie lo clasificó como issue de seguridad, así que ninguna release lo llevó: ocho meses con el fix a un solo commit de distancia, en el repositorio, mientras cada proyecto que empaqueta Brotli seguía distribuyendo el bug adentro. Ahora cada uno de esos proyectos ha tenido que sacar su propia actualización, y el repositorio oficial de Google recién la publicó esta semana con las versiones 1.0.10, 1.1.1 y 1.2.1.

Es la lección incómoda del caso y me la quedo: un fix en el main no es un fix. El CVE solo existe como cosa pública cuando alguien lo etiqueta y llega en una release instalable.

Qué hice en mi flota

Administro VPS con servicios Python: agentes, crons, cosas que hacen decenas de requests salientes a APIs todo el día. Lo primero fue inventariar los entornos virtuales: un python3 -m pip show Brotli brotlicffi en cada uno y mirar la versión. Los parches: Brotli 1.2.1 y brotlicffi 1.2.1.0; Node 22.23.4, 24.22.1 o 26.12.1; Bun 1.4.4; Envoy e Istio con sus propias líneas fijadas. Y si tienes imágenes Docker que empaquetan alguno de estos, los locks de dependencias hay que actualizarlos antes de reconstruir, no después.

Dato parcial: Apache con mod_brotli y Nginx no decodifican Brotli por defecto, así que un server web estático respira tranquilo. Pero no te confíes si tu aplicación acepta cuerpos de petición comprimidos: el proxy no te salva de eso.

Si todavía no puedes subir de versión, los workarounds que apliqué mientras preparaba las actualizaciones: desinstalar Brotli y brotlicffi donde solo eran opcionales (los clientes siguen con gzip y deflate), y rechazar en el proxy toda petición cuyo Content-Encoding incluya «br». Ojo con una: quitar «br» de tus propios Accept-Encoding no alcanza, porque un servidor malicioso puede mandarte Brotli sin que lo pidas; hay que validar el header de la respuesta antes de decodificar, no después.

La cuenta pendiente es la cadena de suministro

Mi opinión va más allá de este CVE puntual. El hueco no es el bug de compresión: es el tiempo entre «ya lo arreglé en el código» y «ya llegó una release parcheada a tu dependency tree». Aquí duró ocho meses, en una librería de 82,8 millones de descargas mensuales. Desde esta semana, además de instalar paquetes, me fijo qué librería nativa empaqueta cada cosa que uso, porque el paquete de Python es solo el chasis: el motor puede ser otro.

Fuente de inspiración: Node2Shell Brotli vuln (CVE-2026-111497) evolves to HTTP2Shell (Aikido)

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *