# CVE-2026-111497 (Node2Shell): qué hace el borde y qué tienes que parchear tú

> El borde rechaza los cuerpos de petición Brotli con el escudo 1009. No parchea tus servidores ni las respuestas que descarga tu código: actualiza Brotli.

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 usan `brotli` o `brotlicffi` y la extensión `brotli` de PHP.
- **Clientes HTTP que decodifican respuestas Brotli**: `fetch()` de Node.js, `HttpClient` de .NET y `requests`, `httpx`, `aiohttp` o `urllib3` de Python cuando `brotli` está instalado. Basta con que un servidor del atacante responda con un cuerpo manipulado.

## Qué hace el borde

El borde tiene un [escudo](https://developers.openwaf.dev/es/waf/shields/#brotli-request-body) 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](https://developers.openwaf.dev/es/waf/block-page/). 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`, `zstd` o `identity` pasan 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](https://developers.openwaf.dev/es/waf/modes-and-levels/#modes) 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](#patch)) y después añade una [excepción del WAF](https://developers.openwaf.dev/es/waf/waf-exceptions/) 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.

**Panel**

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**.
**CLI**

```sh
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"
```
**API**

```sh
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"}'
```
**MCP**

`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.


> **Atención**
>
> Una excepción para el 1009 manda los cuerpos Brotli de esa ruta directamente a tu origen. Añádela solo para un origen que ya esté parcheado.


## 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)](https://developers.openwaf.dev/es/ssl/full-strict/).
- **Los nombres sin proxy**, los sitios en modo `log` y los sitios con el WAF en `off`.
- **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](https://developers.openwaf.dev/es/analytics/security-events/) 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:

```sh
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](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases)
- [Google Brotli: commit del arreglo 0ed4268](https://github.com/google/brotli/commit/0ed4268a4401abcb4472096340477cf4af7d1a2b)
- [Imperva: Node2Shell, de datos Brotli a ejecución remota de código](https://www.imperva.com/blog/node2shell-from-brotli-data-to-remote-code-execution/)
- [JFrog: Brotli2Shell, más allá de Node2Shell y HTTP2Shell](https://research.jfrog.com/post/brotli2shell-beyond-node2shell-and-http2shell/)
- [Sophos: Node2Shell explotada activamente](https://www.sophos.com/en-us/blog/node2shell-cve-2026-111497-in-active-exploitation)
