# Manual operativo — remediación de CVE-2026-111497

El procedimiento que implementan los scripts, escrito para que un auditor humano pueda reproducir,
auditar o anular cada paso. Cada fase nombra su evidencia: el comando cuya salida justifica la
decisión.

## Fase 0 — Inventario del perímetro

Decida qué hosts están en alcance y confirme el acceso root mediante una clave.

```bash
for h in <host-alias-1> <host-alias-2>; do
  ssh "$h" 'grep PRETTY_NAME /etc/os-release; dpkg -l libbrotli1 2>/dev/null | tail -1'
done
```

Criterio de aceptación: cada host responde con un nombre de sistema operativo y, o bien una línea de
paquete, o bien nada.

## Fase 1 — Detección (solo lectura)

`detect.sh` recopila, sin modificar el sistema:

1. Identidad del host y sistema operativo.
2. Versión de `libbrotli1` y su clasificación en la matriz de versiones vulnerables.
3. Si ya hay un backport de la distribución aplicado (el changelog menciona el CVE).
4. El candidato de apt de `-security` tras `apt-get update`.
5. Los consumidores activos de `libbrotlidec` a partir de `/proc/*/maps`.
6. La superficie de decodificación: libcurl, Node, Python, PHP, `ngx_brotli`, `mod_brotli`.
7. Una instantánea de inodos de los archivos `.so` reales, para la comparación posterior de
   mapeos obsoletos.

Veredicto: `SAFE` (0), `VULNERABLE` (1), `NOT_INSTALLED` (3), `ERROR` (10).

Criterio de aceptación: existe `state.before` y contiene `installed`, `candidate` y los tres inodos.

## Fase 2 — Remediación

`remediate.sh` ejecuta una secuencia estricta y se detiene en el primer invariante que falla:

1. **Copia de seguridad** — `.deb` antiguo, `.so` actuales e instantánea de `dpkg -l` en
   `/root/cve-2026-111497-fix-<timestamp>/`.
2. **Puerta de autenticidad** — descarga el candidato y exige `CVE-2026-111497` en su changelog
   empaquetado. Un candidato que solo parece más reciente se rechaza.
3. **Simulación** — `apt-get install --only-upgrade --dry-run`; el conjunto esperado es exactamente
   los paquetes de Brotli y nada más.
4. **Instalación** — `libbrotli1`, más `libbrotli-dev` si estaba instalado antes.
5. **Reinicio de consumidores** — cada unidad de systemd cuyos procesos mapean `libbrotlidec`,
   resuelta a la unidad más interna bajo `/system.slice/` para que se capturen las instancias de
   plantilla; los demonios de panel iniciados como ámbitos transitorios se reinician mediante su
   propia herramienta de control.
6. **Comprobación de inodos** — ningún consumidor de servidor puede seguir mapeando un inodo previo
   al parche.

Criterio de aceptación: código de salida 0 y una línea `REMEDIATED:` con las versiones antigua y
nueva.

## Fase 3 — Verificación

`verify.sh` confirma cinco hechos:

1. La versión del paquete cambió.
2. El changelog instalado menciona `CVE-2026-111497`.
3. Ningún proceso de servidor mapea un inodo previo al parche.
4. `systemctl --failed` está vacío.
5. Un round-trip funcional de decodificación tiene éxito (servicio local `br` o la CLI `brotli`).

Criterio de aceptación: `VERIFY: PASS`, código de salida 0.

## Comprobación cruzada manual (independiente de los scripts)

```bash
dpkg -l | grep -E 'brotli'
apt-cache policy libbrotli1
zgrep -i CVE-2026-111497 /usr/share/doc/libbrotli1/changelog.Debian.gz
# no process may map the pre-patch decoder:
grep -l libbrotlidec /proc/[0-9]*/maps 2>/dev/null | wc -l
```

## Reversión

```bash
dpkg -i /root/cve-2026-111497-fix-<timestamp>/deb/libbrotli1_*.deb
# then restart every service listed in phase 2, step 5
```

La reversión restaura por definición la versión vulnerable. Úsela solo cuando el paquete parcheado
rompa una dependencia, y registre la decisión.

## Mitigación temporal cuando no existe backport

Rechace en el proxy inverso o en el WAF las peticiones que lleven `Content-Encoding: br` (incluidos
los valores compuestos como `gzip, br`) antes de que lleguen a la aplicación, y responda `415
Unsupported Media Type`. Es un paliativo, no un sustituto de la actualización: solo protege los
cuerpos entrantes y deja expuesta toda consulta saliente de libcurl.

## Criterios de cierre

- `detect.sh` devuelve 0 en una nueva ejecución, o `verify.sh` devuelve `VERIFY: PASS` tras la
  remediación.
- El directorio de copia de seguridad existe y no está vacío.
- Los sitios alojados responden con su estado previo al cambio.
- Los consumidores de escritorio diferidos quedan registrados en el informe, con la expectativa de
  que cargarán la biblioteca parcheada en el siguiente inicio de sesión o reinicio.
