CVE-2026-111497, también llamada Node2Shell, HTTP2Shell o Brotli2Shell, es una escritura fuera de límites en el decodificador Brotli en C de Google (DecodeBlockTypeAndLength en c/dec/decode.c). Está corregida en Brotli 1.2.1. Un flujo Brotli manipulado puede dar a un atacante ejecución remota de código en cualquier proceso que lo decodifique. Tiene una puntuación CVSS de 9,2, está en el catálogo de vulnerabilidades explotadas conocidas (KEV) de CISA desde el 2026-10-27 y se está explotando.
Te afecta por dos vías:
- Servidores que decodifican cuerpos de petición enviados con
Content-Encoding: br: Express 5 / body-parser 2.x (raw(),json()…) en Node.js anterior a 22.23.4, 24.22.1 y 26.12.1, la descompresión de peticiones de ASP.NET Core, la interfaz HTTP de ClickHouse, servicios Python que usanbrotliobrotlicffiy la extensiónbrotlide PHP. - Clientes HTTP que decodifican respuestas Brotli:
fetch()de Node.js,HttpClientde .NET yrequests,httpx,aiohttpourllib3de Python cuandobrotliestá instalado. Basta con que un servidor del atacante responda con un cuerpo manipulado.
Qué hace el borde
El borde tiene un escudo nuevo, el 1009 «Brotli Request Body». Rechaza toda petición con cuerpo cuyo Content-Encoding incluya br, antes de que llegue a tu origen. La cabecera se compara sin distinguir mayúsculas y br cuenta en cualquier posición de la lista: gzip, br o repartida en varias líneas Content-Encoding. La petición recibe un 403 con tu página de bloqueo. El borde no decodifica los cuerpos de petición para buscar el exploit.
Nada más cambia:
- las peticiones sin cuerpo y los cuerpos codificados con
gzip,deflate,zstdoidentitypasan como antes; - las respuestas no se tocan;
- los navegadores nunca envían cuerpos de petición Brotli, así que tus visitantes no lo notan.
Como todos los escudos, el 1009 sigue el modo del sitio: bloquea en active, solo registra en log (la petición llega al origen) y no se ejecuta con el WAF en off.
El decodificador Brotli del propio borde es un port a Go. Tiene el mismo fallo de lógica pero sin corrupción de memoria (en Go era un cierre inesperado, GHSA-c9gr-gmg4-2vqv). Ya está actualizado, y un error al decodificar solo termina ese flujo.
Si tu aplicación recibe cuerpos de petición Brotli
Algunas API aceptan con razón cuerpos comprimidos con Brotli, por ejemplo un endpoint de ingesta que alimentan tus propios agentes. Parchea primero ese origen (más abajo) y después añade una excepción del WAF para la regla 1009 solo en esa ruta, limitada al nombre que la necesita. Una excepción con rule_id 0 no apaga el escudo.
Dominio → Seguridad → Firewall → Reglas → Excepciones del WAF → Añadir excepción del WAF. Indica 1009 como Regla del WAF, la Ruta (por ejemplo /v1/ingest), el nombre en Se aplica a y una Nota.
openwaf-cloud ctl rules add example.com kind=waf_exception rule_id=1009 path_pattern='/v1/ingest' \
hosts:='["api.example.com"]' note="Origen parcheado, acepta cuerpos br" --reason "CVE-2026-111497: cuerpos br en /v1/ingest"curl -sS -X POST "https://dash.openwaf.dev/v1/orgs/$ORG/zones/example.com/rules" \
-H "Authorization: Bearer $OPENWAF_TOKEN" \
-H "X-Change-Reason: CVE-2026-111497: cuerpos br en /v1/ingest" \
-H "Content-Type: application/json" \
-d '{"kind": "waf_exception", "rule_id": 1009, "path_pattern": "/v1/ingest", "hosts": ["api.example.com"], "note": "Origen parcheado, acepta cuerpos br"}'add_rule con {"zone": "example.com", "kind": "waf_exception", "rule_id": 1009, "path_pattern": "/v1/ingest", "hosts": ["api.example.com"], "reason": "CVE-2026-111497: cuerpos br en /v1/ingest"}; simula y después confirma.
Qué no cubre el borde
- Las respuestas que descarga tu código. Si tus servidores o scripts llaman a
fetch()u otro cliente HTTP con una URL que un atacante puede elegir, la respuesta Brotli manipulada les llega directamente. El borde solo ve las peticiones a tus nombres con proxy. - El tráfico que se salta el borde. Quien llega a tu origen directamente, por su dirección IP o por otro nombre, no pasa ninguna inspección. Acepta conexiones solo desde el borde de OpenWAF y usa TLS al origen en modo Full (strict).
- Los nombres sin proxy, los sitios en modo
logy los sitios con el WAF enoff. - Otras formas de hacer llegar datos Brotli a tu software: ficheros subidos, colas, brokers de mensajes, ficheros en almacenamiento.
Qué tienes que parchear
| Software | Corregido en |
|---|---|
| Node.js | 22.23.4, 24.22.1 o 26.12.1 y posteriores. Las ramas sin soporte no reciben arreglo: pasa a una rama con soporte. Comprueba también node -v dentro de tus imágenes de contenedor, no solo en el host. |
brotli / brotlicffi de Python | Las versiones construidas sobre Brotli 1.2.1. |
| PHP | Las versiones de php.net del 2026-10-26. |
| .NET | La actualización de mantenimiento de octubre de 2026. |
libbrotli del sistema operativo | La actualización de seguridad de tu distribución; después reinicia los servicios que la cargan. |
| Cualquier otro software que incluya Brotli anterior a 1.2.1 | Su versión parcheada: FFmpeg, libjxl, ClickHouse, Apache Arrow y otros. |
Comprobar si te han atacado
Las peticiones rechazadas aparecen en los eventos de seguridad con rule_id 1009 y rule_name Brotli Request Body. En Analítica › Tráfico → Eventos de seguridad, elige Añadir filtro → Regla es 1009, o pregunta a la API:
curl -s "https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/events?rule_id=1009&since=2026-10-27T00:00:00Z" \
-H "Authorization: Bearer $OPENWAF_TOKEN"Un evento anterior a tu parche solo indica que alguien lo intentó a través del borde. No dice si tu origen recibió el ataque por otra vía. Revisa también los logs del propio origen.
Fuentes
- Node.js: versiones de seguridad de octubre de 2026 (enlace externo)
- Google Brotli: commit del arreglo 0ed4268 (enlace externo)
- Imperva: Node2Shell, de datos Brotli a ejecución remota de código (enlace externo)
- JFrog: Brotli2Shell, más allá de Node2Shell y HTTP2Shell (enlace externo)
- Sophos: Node2Shell explotada activamente (enlace externo)