Zurück
2026/10/26
HTTP2Shell (CVE-2026-111497): Ein aktualisiertes Binary patcht keine laufenden Prozesse
Die Brotli-Lücke hinter HTTP2Shell betrifft Node.js, Bun und Python. So finden Sie echte Exposition in laufenden Prozessen und starten KI-Agenten sicher neu.
Am 21. Oktober 2026 veröffentlichte Node.js Fixes für CVE-2026-111497, einen Out-of-Bounds-Write im Brotli-Decoder von Google. Innerhalb weniger Tage folgten Advisories für Bun, die Python-Pakete brotli und brotlicffi, Envoy und Istio; die Fachpresse taufte die Lücke Node2Shell und später HTTP2Shell. Trotz des Namens handelt es sich nicht um einen Fehler im HTTP/2-Protokoll. Es ist ein Dekompressionsfehler, und er ist überall relevant, wo Software Brotli-Daten dekodiert, die ein Angreifer beeinflussen kann.
Dieser Artikel zeigt, was belegt ist, was nur möglich ist und wie Sie Ihre eigenen Systeme prüfen. Außerdem behandelt er eine Lehre aus unserer eigenen Reaktion: Ein installiertes, gefixtes Binary behebt nichts an einem Prozess, der noch das alte ausführt. In unserer Umgebung behielten lang laufende Claude-Code-Sitzungen ihre alten eingebetteten Runtimes, obwohl das installierte Claude Code bereits aktualisiert war.
Das Wichtigste in Kürze
- Betroffen: Upstream-Brotli 1.0.3 bis 1.2.0. Behoben: 1.0.10, 1.1.1 und 1.2.1. Produkte, die Brotli mitbringen, brauchen ein eigenes gefixtes Release.
- Exposition erfordert einen echten Pfad: vom Angreifer beeinflusste Brotli-Daten, die einen verwundbaren Decoder erreichen. Ein Produktname oder Netzwerkzugriff allein ist kein Beleg.
- Prüfen Sie laufende Prozesse, nicht nur installierte Pakete. Ein Prozess behält die Runtime, mit der er gestartet wurde, bis er neu gestartet wird.
- Starten Sie zustandsbehaftete KI-Agenten einzeln neu und übergeben Sie vorher deren Events, Freigaben und Arbeitsstand.
1. Worum es bei der Schwachstelle geht
Traf der Decoder auf einen ungültigen Block-Switch, meldete er „mehr Eingabe nötig“ statt eines dauerhaften Formatfehlers. Ein streamender Aufrufer lieferte daraufhin weiter Bytes nach, und der Decoder hängte sie an einen internen Puffer von acht Byte an – und schrieb über dessen Ende hinaus. Laut Node.js-Advisory kann ein Angreifer, der Brotli-Daten liefern kann, die eine Anwendung mit node:zlib dekomprimiert, „den Prozessspeicher beschädigen, was zu einem Absturz, zur Offenlegung von Prozessspeicher oder zur Ausführung von Remote-Code führen kann“.
Die Schweregrade unterscheiden sich je nach Quelle. Node.js stuft die Lücke als High ein. Das GitHub-Advisory für die Python-Pakete und das Envoy-Advisory bewerten sie als Critical, CVSS-4.0-Score 9.2. Ubuntu führt sie derzeit mit Priorität Medium. Mit Stand 26. Oktober nennt die CISA-Bewertung im CVE-Eintrag die Ausnutzung „none“, und die CVE steht nicht im Known-Exploited-Vulnerabilities-Katalog der CISA. Das Node.js-Advisory nennt dennoch Remote-Code-Ausführung als mögliche Folge – fehlende Meldungen über Angriffe sind also kein Grund zum Abwarten.
2. Voraussetzungen: Wann Sie tatsächlich exponiert sind
Alle drei Bedingungen müssen erfüllt sein:
- Ein verwundbarer Decoder ist geladen im Prozess: eine mitgelieferte oder System-Brotli-Bibliothek im betroffenen Bereich ohne Fix oder Backport.
- Etwas ruft ihn auf: explizite Dekompression oder automatisches Dekodieren von
Content-Encoding: br. - Die Eingabe ist vom Angreifer beeinflussbar: Antworten von beliebigen URLs, hochgeladene Dateien, eingehende Request-Bodies oder Klartext-HTTP-Verkehr in einem feindlichen Netzwerk.
Das automatische Dekodieren ist der Pfad, den Teams am häufigsten übersehen. Laut Bun-Advisory sendet fetch standardmäßig Accept-Encoding: br und dekodiert die Antwort; jedes Bun-Programm, das nicht vertrauenswürdige URLs abruft, hat also einen Pfad. In Python dekodiert urllib3 automatisch Antworten mit Content-Encoding: br, sobald brotli oder brotlicffi installiert ist, und auch requests bietet in seinen Anfragen br an. Das passiert selbst dann, wenn Ihr eigener Code Brotli nirgends erwähnt. Envoy und Istio sind nur exponiert, wenn ein Brotli-Dekompressor konfiguriert ist.
3. Bestätigt betroffen oder nur möglicherweise
Stand: 26. Oktober 2026. Prüfen Sie die verlinkten Advisories, denn die Lage ändert sich schnell.
| Komponente | Status | Behoben in |
|---|---|---|
| Upstream-Brotli (C) | Bestätigt: 1.0.3 bis 1.2.0 | 1.0.10, 1.1.1, 1.2.1 |
| Node.js 22, 24, 26 | Bestätigt | 22.23.4, 24.22.1, 26.12.1 |
| Node.js 20 und älter (End of Life) | Nicht bewertet; Node.js betrachtet End-of-Life-Linien grundsätzlich als betroffen | Auf eine unterstützte Linie wechseln |
| Bun (einschließlich kompilierter Executables) | Bestätigt: 1.0.21 bis 1.4.3 | 1.4.4, kompilierte Apps neu bauen |
| Python brotli / brotlicffi | Bestätigt: ab 1.0.3 | 1.2.1 / 1.2.1.0 |
| Envoy (Brotli-Dekompressor konfiguriert) | Bestätigt | 1.40.0, 1.39.3, 1.38.6, 1.37.8 (1.36.12 im nicht mehr unterstützten 1.36-Zweig) |
| Istio (Brotli-Dekompression aktiviert) | Bestätigt | 1.31.2, 1.30.6, 1.29.9 (das letzte 1.29-Release) |
| Ubuntu-Paket brotli | Bewertung ausstehend (alle Releases) | Noch kein gefixtes Paket |
| Ubuntu-Paket nodejs | Verwundbar unter 20.04 (mitgeliefertes Brotli). Ab 22.04 nutzt es das System-Brotli und folgt damit der Zeile darüber | Siehe Ubuntu-Tracker |
| Debian-Paket brotli | Behoben in bookworm und trixie; forky noch nicht | 1.0.9-2+deb12u1, 1.1.0-2+deb13u1 |
| Chrome, Electron und Electron-Apps | Unbekannt: keine Herstelleraussage gefunden | Release Notes der Hersteller beobachten |
Zur letzten Zeile: Chrome und Electron bringen eigene Brotli-Kopien mit, und eine Electron-App bettet zusätzlich eine Node.js-Runtime ein. Zum Zeitpunkt des Schreibens führen die neuesten stabilen Electron-Releases (45.0.0, 44.9.3 und 43.8.3, alle vom 21. Oktober) Node.js 24.22.0 statt 24.22.1, und ihre Release Notes erwähnen diese CVE nicht. Electron-Pre-Releases vom 23. Oktober enthalten Node.js 24.22.1; ein stabiler Fix ist also wahrscheinlich, aber noch nicht erschienen. Eine Desktop-App auf Electron-Basis ist damit möglicherweise exponiert, nicht bestätigt verwundbar. Dasselbe gilt für Chat-Clients und KI-Desktop-Tools: Prüfen Sie die Aussage des jeweiligen Herstellers, bevor Sie sie als betroffen oder sicher einstufen.
Noch eine Falle: Eine gemeldete Bibliotheksversion beweist weder das eine noch das andere. Ein gefixtes Node.js 22.23.4 meldet process.versions.brotli weiterhin als 1.1.0, weil der Fix zurückportiert wurde. Distributionen machen es genauso. Maßgeblich ist die gefixte Version des Produkts oder der Sicherheitsstatus der Distribution, nicht der Brotli-Versionsstring.
4. Was wir in unserer eigenen Umgebung gefunden haben
Bevor wir etwas änderten, haben wir eine rein lesende Bestandsaufnahme gemacht. Hier unsere Beobachtungen, anonymisiert, wobei bestätigte Befunde getrennt von nicht verifizierbarem Risiko aufgeführt sind.
Bestätigte Beobachtungen
- Das installierte Claude Code war bereits aktualisiert, aber ein Dutzend lang laufender Sitzungen lief noch mit älteren Builds, die Wochen zuvor gestartet worden waren. Sie waren nie neu gestartet worden.
- Bei unserer ersten Zählung fehlten drei davon. Sie liefen unter einem anderen Hilfsprozess, sodass eine Suche nach der Kommandozeile nicht griff. Die Suche nach dem Executable fand sie.
- Die Dateien der alten Builds hatte der Updater bereits von der Platte gelöscht, daher ließ sich die eingebettete Bun-Version dieser Prozesse nicht auslesen.
- Eine übrig gebliebene Paketmanager-Installation eines älteren Claude-Code-Builds enthielt Bun 1.4.0. Im Normalbetrieb nutzte sie nichts, ein Fallback-Pfad hätte es aber tun können. Wir haben sie entfernt, nachdem wir gezeigt hatten, dass nichts davon abhing.
- Auf einem Server war noch eine ungenutzte Node.js-Runtime im End of Life installiert. Wir haben sie auf dieselbe Weise entfernt.
- Der aktuelle Claude-Code-Build, auf den wir aktualisiert haben (2.1.310), enthält Bun 1.4.4. Das haben wir durch Untersuchung des Binarys bestätigt. Das Changelog von Anthropic erwähnt die CVE nicht; prüfen Sie Ihren eigenen Build also auf dieselbe Weise.
Nicht verifiziert, als Risiko behandelt
- Ob die alten Sitzungen tatsächlich verwundbar waren. Ihre Bun-Version war nicht lesbar. Das gefixte Bun 1.4.4 erschien erst um den 22. Oktober, nach diesen Builds; deshalb haben wir sie als betroffen behandelt.
- Ob ein Angreifer den Decoder über diese Sitzungen hätte erreichen können, etwa durch Abruf einer bösartigen URL. Dieser Pfad ist aufgrund des dokumentierten
fetch-Verhaltens von Bun plausibel, nachgewiesen haben wir ihn aber nicht. - Ob andere Software mit eigener Brotli-Kopie betroffen ist. Wo es keine Herstelleraussage gibt, verfolgen wir das Produkt anhand der Hersteller-Releases, statt es als sicher oder verwundbar anzunehmen.
Wir haben keine Hinweise auf eine Ausnutzung gefunden. Das haben wir aber auch nicht als Beweis für Sicherheit gewertet: Die Lösung bestand darin, die Exposition zu beseitigen, nicht darin, sie wegzuargumentieren.
5. Checkliste für Erkennung und Behebung
Abhängigkeiten finden
Suchen Sie Brotli dort, wo es mitgeliefert wird, nicht nur dort, wo es als Paket installiert ist. Prüfen Sie Ihre SBOMs und Container-Images auf Node.js, Bun, Python-Pakete, Envoy und statisch gelinktes Brotli. Prüfen Sie transitive Python-Abhängigkeiten, denn Brotli kommt oft als optionales Extra hinzu.
# Node.js: compare with 22.23.4 / 24.22.1 / 26.12.1
node -p process.version
# Python packages: run once per interpreter and virtual environment
python -m pip list 2>/dev/null | grep -iE '^(brotli|brotlicffi) '
pipdeptree -r -p brotli # what pulled it in
# Debian / Ubuntu system library (then check the distro tracker)
dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\n' 'libbrotli*'
# Container images, with an SBOM scanner such as Syft
syft <image> | grep -iE 'brotli|node|bun'
Eingebettete Runtimes finden
Programme, die mit bun build --compile gebaut wurden, enthalten eine eigene Kopie von Bun. Laut Bun-Advisory bleiben sie betroffen, bis sie mit 1.4.4 neu gebaut werden. Ein Bun-Upgrade auf dem Build-Rechner ändert nichts an bereits ausgerollten Binaries.
# The Bun version inside a compiled executable
grep -aoE 'Bun v1\.[0-9]+\.[0-9]+' /path/to/binary | sort -u
Laufende Prozesse finden
Prüfen Sie, was läuft, nicht, was installiert ist. Unter Linux zeigt ein Prozess, dessen Executable ersetzt oder entfernt wurde, (deleted) an. Das ist ein starkes Indiz dafür, dass er noch einen alten Build ausführt.
# Processes still running a deleted (replaced) executable (run as root to see all users)
for p in /proc/[0-9]*; do
e=$(readlink "$p/exe" 2>/dev/null) || continue
case "$e" in *"(deleted)") echo "${p#/proc/} $e";; esac
done
# Processes older than the fix
pgrep -af 'node|bun|claude' # then: ps -o pid,lstart,args -p <pid>
Unter macOS zeigt lsof -p <pid> das Executable, das ein Prozess geladen hat. Gleichen Sie nach Executable ab, nicht nach Prozessname, sonst übersehen Sie Hilfsprozesse und Hintergrund-Worker.
Beheben, neu bauen, neu ausrollen
- Aktualisieren Sie auf die gefixten Versionen aus der Tabelle. Nutzen Sie das gepatchte Paket Ihrer Distribution, wo ein Backport existiert.
- Bauen Sie Container-Images und kompilierte Executables neu und rollen Sie sie erneut aus. Ein gepatchtes Base-Image nützt nichts für ein Image, das Sie nicht neu gebaut haben.
- Entfernen Sie ungenutzte Runtimes und Installationsreste, nachdem Sie nachgewiesen haben, dass kein Dienst, Job oder Skript davon abhängt. Halten Sie ein Rollback bereit.
- Wo es noch keinen Fix gibt, deaktivieren Sie das Brotli-Dekodieren nicht vertrauenswürdiger Eingaben, wo dies gefahrlos möglich ist. Für Bun funktioniert
fetch(url, { decompress: false })pro Request. Geben Sie jeder Mitigation einen Verantwortlichen und ein Enddatum.
Neu starten und verifizieren
Prüfen Sie nach dem Neustart das tatsächliche Executable und die Runtime-Version des neuen Prozesses. Prüfen Sie dann das fachliche Ergebnis: Queues abgearbeitet, geplante Jobs erfolgreich, Monitoring-Alarme kommen an. Ein erfolgreicher Upgrade-Befehl beweist nur, dass der Befehl gelaufen ist.
6. Persistente KI-Agenten sicher neu starten
Lang laufende KI-Agenten halten Zustand: ausstehende Tool-Aufrufe, Freigaben, Nachrichten in der Warteschlange und übernommene Aufgaben. Alle gleichzeitig neu zu starten, kann diesen Zustand vernichten. Diese Reihenfolge hat sich bei uns bewährt:
- Jede Sitzung erfassen: Version des Executables, Zustand (idle, wartend oder beschäftigt), letzte Aktivität, ausstehende Arbeit, Freigaben, auf die sie wartet oder die sie hält, nicht quittierte Events und wie sie wiederhergestellt wird.
- Freigaben aus dem Speicher holen. Eine Freigabe, die nur in der Konversation einer Sitzung existiert, geht beim Neustart verloren. Halten Sie vor dem Neustart jede ausstehende Freigabe (was freigegeben wurde, von wem, für welche genaue Änderung) dauerhaft fest, etwa im Ticket oder Pull Request. Bestätigen Sie danach, dass die Sitzung sie noch sieht. Im Zweifel holen Sie die Freigabe erneut ein, statt sie vorauszusetzen.
- Zuerst den Ersatz nachweisen. Bestätigen Sie, dass Sitzungen auf dem gefixten Build bereits funktionieren und dass ein von den alten Sitzungen unabhängiger Event-Watcher läuft, sodass kein Event von einer neu zu startenden Sitzung abhängt.
- Zuerst untätige Sitzungen neu starten, eine nach der anderen. Verifizieren Sie nach jeder, dass der alte Prozess beendet ist, der neue Prozess das gefixte Executable ausführt, der Konversationsverlauf intakt ist und eine etwaige Remote-Verbindung wieder steht. Dann folgt die nächste.
- Den am stärksten ausgelasteten Owner zuletzt neu starten, zwischen zwei Aufgaben. Lassen Sie ihn eine Übergabenotiz schreiben, stoppen Sie seinen Watcher erst bei null ausstehenden und null nicht quittierten Events, starten Sie neu und bestätigen Sie dann, dass sein Watcher an der gespeicherten Position ohne Lücken weitergemacht hat.
- Mit Eingaben in der Warteschlange beim Wiederverbinden rechnen. Eine unserer neu gestarteten Sitzungen erhielt eine Nachricht, die zehn Tage gewartet hatte, und handelte danach. Prüfen Sie vor dem Neustart den Posteingang jeder Sitzung und informieren Sie deren Owner.
- Anhalten und eskalieren, wenn ein Schritt nicht belegen kann, dass die Arbeit wiederhergestellt wurde. Greifen Sie nicht darauf zurück, einfach alles zu beenden.
Legen Sie vorher fest, was „erledigt“ heißt. Erledigt bedeutet: kein laufender Prozess auf einem betroffenen Build, jede Ausnahme mit Verantwortlichem und Wiedervorlagedatum dokumentiert, und die fachlichen Prüfungen bestehen. „Das Paket wurde aktualisiert“ ist nicht erledigt.
Quellen
- CVE-Eintrag: CVE-2026-111497
- Node.js-Sicherheitsreleases Oktober 2026
- Bun-Advisory GHSA-663w-cv8g-jj2p
- Advisory für Python brotli / brotlicffi GHSA-9v8h-qqgm-4m35
- Envoy-Advisory GHSA-3wvj-j6qm-62mr
- Istio-Sicherheitsbulletin ISTIO-SECURITY-2026-007
- Ubuntu-CVE-Tracker: CVE-2026-111497
- Debian-Security-Tracker: CVE-2026-111497
- Electron-Releases
Global
Japan
Korea
China
Taiwan
Vietnam
Thailand
Indonesia
Portugal
Spain
France
Egypt
Russia