# CVE-2026-111497 — Brotli-Agent zur Behebung

Ein deterministischer Detektor, Remediator und Verifizierer für **CVE-2026-111497** — ein
Out-of-Bounds-Schreibzugriff im Google-Brotli-Decoder (`c/dec/decode.c`, CWE-787). Drei
Shell-Skripte führen die vollständige Prüfung durch und liefern ein kompaktes Urteil; das
Sprachmodell orchestriert und liest eine Zeile, statt den Host von Hand zu erkunden.

<!-- md-i18n:switcher -->
**In anderen Sprachen:** [English](README.md) · Deutsch · [中文](README.zh.md) · [हिन्दी](README.hi.md) · [Español](README.es.md) · [Русский](README.ru.md)

[![CI](https://github.com/paulmann/CVE-2026-111497/actions/workflows/ci.yml/badge.svg)](https://github.com/paulmann/CVE-2026-111497/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/paulmann/CVE-2026-111497)](https://github.com/paulmann/CVE-2026-111497/releases)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Shell: bash](https://img.shields.io/badge/shell-bash-4EAA25.svg)](#voraussetzungen)
[![Platform: Debian/Ubuntu](https://img.shields.io/badge/platform-Debian%20%7C%20Ubuntu-A80030.svg)](#voraussetzungen)

![CVE-2026-111497 — Brotli-Agent zur Behebung](assets/social-preview.svg)

## Inhalt

- [Warum es dieses Werkzeug gibt](#warum-es-dieses-werkzeug-gibt)
- [Expositionsmodell](#expositionsmodell)
- [Schnellstart](#schnellstart)
- [Urteil und Exit-Code-Vertrag](#urteil-und-exit-code-vertrag)
- [Was die Prüfung abdeckt](#was-die-prüfung-abdeckt)
- [Aufbau des Repositories](#aufbau-des-repositories)
- [Voraussetzungen](#voraussetzungen)
- [Grenzen](#grenzen)
- [Dokumentation](#dokumentation)
- [Sprachen](#sprachen)
- [Mitwirken](#mitwirken)
- [Lizenz](#lizenz)

[Wiki](https://github.com/paulmann/CVE-2026-111497/wiki) · [Changelog](CHANGELOG.md) · [Security](SECURITY.md) · [English](README.md)

## Warum es dieses Werkzeug gibt

Eine vollständige Brotli-Prüfung ist kein Versionsvergleich. Sie verlangt pro Host die Antwort
auf vier Fragen: welches Paket installiert ist, ob die laufenden Prozesse den verwundbaren
Decoder noch eingebunden haben, welche Anwendungspfade tatsächlich nicht vertrauenswürdige
Brotli-Daten decodieren und ob der Backport der Distribution die eigentliche Korrektur ist statt
eines unabhängigen Neubaus.

Von Hand beantwortet kosten diese Fragen Dutzende Werkzeugaufrufe pro Host und erzeugen Prosa,
die sich nicht nachprüfen lässt. Hier beantworten Skripte sie mit einem festen
Exit-Code-Vertrag:

| Befehl | Wirkung auf dem Host | Ausgabe für den Agenten |
|---|---|---|
| `detect.sh` | nur lesend | `VERDICT: SAFE\|VULNERABLE\|NOT_INSTALLED` |
| `remediate.sh` | einziger Änderungspunkt | `REMEDIATED: <old> -> <new>` |
| `verify.sh` | nur lesend | `VERIFY: PASS\|FAIL` |

## Expositionsmodell

Der verwundbare Code ist der **Decoder**, nicht der Encoder. Dienste, die Antworten nur mit
Brotli komprimieren, sind keine Angriffsfläche; Dienste, die nicht vertrauenswürdige
Brotli-Daten dekomprimieren, sind es.

| Erreichbarer Decode-Pfad | Typischer Träger |
|---|---|
| HTTP-Anfragekörper | `Content-Encoding: br`, an die Anwendung gesendet |
| Ausgehende HTTP-Clients | `fetch()`, libcurl mit leerem `CURLOPT_ENCODING` (alle akzeptieren) |
| Eingehende Antworten von Proxys | Envoy/Istio-HTTP-Decompressor |
| Hoch- oder heruntergeladene Archive | Brotli-Streaming auf Anwendungsebene |
| Mitgelieferte Laufzeitumgebungen | Node.js, Bun, Python `Brotli`/`brotlicffi`, .NET-Request-Dekompression |

Verwundbare Upstream-Versionen sind **1.0.3 bis 1.2.0**. Korrigierte Versionen sind **1.0.10,
1.1.1 und 1.2.1** (veröffentlicht am 21. Oktober 2026), dazu jeder Backport einer Distribution,
der die CVE im mitgelieferten Changelog nennt.

## Schnellstart

```bash
# 1. Deliver the scripts once (host is an SSH alias from ~/.ssh/config)
scp src/common.sh src/detect.sh src/remediate.sh src/verify.sh <host>:/root/cve-2026-111497/

# 2. Audit — read-only
ssh <host> 'bash /root/cve-2026-111497/detect.sh'          # exit 0/1/3/10

# 3. Remediate — only when the verdict is VULNERABLE
ssh <host> 'bash /root/cve-2026-111497/remediate.sh'

# 4. Verify the actual effect
ssh <host> 'bash /root/cve-2026-111497/verify.sh'          # VERIFY: PASS|FAIL
```

## Urteil und Exit-Code-Vertrag

| Code | Urteil | Bedeutung | Nächster Schritt |
|---:|---|---|---|
| 0 | `SAFE` | installierte Version liegt außerhalb des verwundbaren Bereichs, oder ein Distributions-Backport ist bereits eingespielt | dokumentieren und abschließen |
| 1 | `VULNERABLE` | installierte Upstream-Version liegt im verwundbaren Bereich und kein Backport vorhanden | `remediate.sh` ausführen |
| 3 | `NOT_INSTALLED` | `libbrotli1` fehlt auf dem Host | dokumentieren; erneut prüfen, wenn Brotli dazukommt |
| 10 | `ERROR` | Vorbedingung oder Invariante verletzt | Meldung lesen, eskalieren, nicht erzwingen |
| 1 (`verify.sh`) | `FAIL` | die Behebung hat nicht gewirkt | untersuchen, bevor der Abschluss erklärt wird |

`remediate.sh` endet mit Code 10, bevor das System berührt wird, wenn der apt-Kandidat gleich
der installierten Version ist oder wenn das Changelog des Kandidaten `CVE-2026-111497` nicht
nennt.

## Was die Prüfung abdeckt

| Prüfung | Mechanismus | Warum sie zählt |
|---|---|---|
| Installierte Version und Upstream-Version | `dpkg-query`, Epoch und Revision entfernt | Distributionsrevisionen verbergen die Upstream-Version |
| Eingespielter Backport | mitgelieferte `changelog.Debian.gz` mit Nennung der CVE | das maßgebliche Signal, nicht die Versionszeichenkette |
| apt-Kandidat | `apt-get update`, dann `apt-cache policy` | entscheidet, ob überhaupt eine unterstützte Korrektur existiert |
| Laufende Nutzer | `/proc/<pid>/maps`-Scan nach `libbrotlidec` | eine gepatchte Datei patcht keinen laufenden Prozess |
| Decode-Oberfläche | libcurl-Brotli-Feature, Node/Bun/Python/PHP-Module, `ngx_brotli`, `mod_brotli` | trennt Decode-Pfade von reinen Kompressionspfaden |
| Decode-Primitive der Anwendung | Anzahl der PHP-Dateien mit `CURLOPT_ENCODING` / `CURLOPT_ACCEPT_ENCODING` | WordPress, SimplePie und Guzzle akzeptieren jede Kodierung, auch `br` |
| Inode-Snapshot vor dem Patch | `find -type f -printf '%i'` auf der echten `.so` | der Inode des Symlinks ist ein falscher Anker |

## Aufbau des Repositories

```text
src/
  common.sh      logging, version parsing, classification matrix, state_get
  detect.sh      read-only audit: verdict, JSON report, before-state
  remediate.sh   backup, authenticity gate, dry-run, install, restart, inode check
  verify.sh      version, CVE reference, stale mappings, failed units, round-trip
docs/
  THREAT-MODEL.md  decode-path exposure model and attack surface
  PLAYBOOK.md      phase-by-phase procedure for a human auditor
  FIELD-REPORT.md  anonymised results from three production hosts
wiki/             operator documentation, field cases, advisory digest
SKILL.md          agent skill: the minimal orchestration playbook
AGENTS.md         repository rules and invariants
```

## Voraussetzungen

- Zielhost: Debian 12, Ubuntu 24.04 oder Ubuntu 26.04 mit `apt`, root über einen SSH-Schlüssel.
- `bash` 5.x, `dpkg`, `apt-get`, `systemd`; `curl` und `brotli` sind optional und erweitern nur
  den funktionalen Rundlauf.
- Kein Netzwerkzugriff der Werkzeuge über die Paketquellen der Distribution hinaus.
- Ausgabestatus: `/var/lib/cve-2026-111497/` (`report.json`, `state.before`, `state.after`).
- Sicherungen: `/root/cve-2026-111497-fix-<timestamp>/` mit altem `.deb`, aktueller `.so` und
  einem `dpkg`-Snapshot.

## Grenzen

- **Nur apt.** rpm-basierte Hosts, Alpine und Container-Basisimages liegen außerhalb des
  Geltungsbereichs; die Klassifikationsmatrix ist portabel, der Behebungspfad nicht.
- **Keine Erkennung statischer Bindung.** Eine in ein Binärprogramm oder ein Container-Image
  einkompilierte Brotli-Kopie ist für `dpkg` unsichtbar. Der Detektor meldet Laufzeitversionen,
  die er lesen kann, und nichts darüber hinaus.
- **Keine Orchestrierungsschicht.** Envoy, Istio, .NET, Bun und Deno sind im Bedrohungsmodell
  beschrieben, werden von den Skripten aber nicht behoben.
- **Desktop- und Infrastruktur-Konsumenten werden zurückgestellt, nicht neu gestartet.** Font-
  und GUI-Stapel binden `libbrotlidec` über freetype ein; ein Neustart würde die Sitzung
  beenden. Sie werden als `deferred` gemeldet und laden die gepatchte Bibliothek bei der
  nächsten Anmeldung oder beim nächsten Neustart.
- **`needrestart` kann zuvorkommen.** Unter Ubuntu 24.04 startet der Paket-Hook Serverdienste
  während der Installation neu, sodass der Neustartabschnitt berechtigterweise nichts mehr zu
  tun findet.
- **Die Felddaten umfassen drei Hosts.** Der Bericht ist eine Stichprobe, keine Bestandsaufnahme
  des Fuhrparks.

## Dokumentation

| Dokument | Inhalt |
|---|---|
| [`docs/THREAT-MODEL.de.md`](docs/THREAT-MODEL.de.md) | Expositionsmodell, Inventar der Decode-Pfade, Begründung der Einstufung |
| [`docs/PLAYBOOK.de.md`](docs/PLAYBOOK.de.md) | das Verfahren, das die Skripte umsetzen, für einen menschlichen Prüfer |
| [`docs/FIELD-REPORT.de.md`](docs/FIELD-REPORT.de.md) | drei Hosts, neun im Feld gefundene Defekte, Nachweise der Verifikation |
| [Wiki](https://github.com/paulmann/CVE-2026-111497/wiki) | Feldberichte mit Ursachen, Advisory-Digest, Betriebs-Runbook |

## Sprachen

Englisch ist die Referenzsprache: ein Dokument ohne Sprachsuffix ist die Quelle der Wahrheit.
Jede Übersetzung trägt das Suffix ihrer Sprache und verlinkt zurück auf die kanonische Datei.

| Sprache | Dateien |
|---|---|
| Englisch (kanonisch) | `README.md`, `AGENTS.md`, `SKILL.md`, `docs/*.md` |
| Russisch | `*.ru.md` |
| Deutsch | `*.de.md` |
| Spanisch | `*.es.md` |
| Chinesisch | `*.zh.md` |
| Hindi | `*.hi.md` |

## Mitwirken

Korrekturen und neue Distributions-Backports sind willkommen. Zuerst [`CONTRIBUTING.md`](CONTRIBUTING.md)
lesen: der Exit-Code-Vertrag, die Regel „Sicherung vor der Änderung“ und das Gate zur
Echtheitsprüfung sind nicht verhandelbar. Sicherheitsmeldungen folgen [`SECURITY.md`](SECURITY.md).

## Lizenz

MIT. Das Werkzeug ist defensiv; es enthält keine Zugangsdaten, keine Infrastruktur-Kennungen und
keine Zieladressen.
