Node2Shell: die Brotli-Lücke CVE-2026-111497 in Node.js, Python und .NET schließen
Am 21. Oktober 2026 hat Node.js eine Lücke im mitgelieferten Brotli-Decoder geschlossen. Inzwischen ist klar, dass der Fehler in Googles Brotli-Bibliothek selbst sitzt und weit über Node.js hinausreicht: bis zu Python-Paketen, .NET, Bun, Envoy und den Paketen der Linux-Distributionen. Ob Sie betroffen sind, entscheidet nicht die Versionsnummer allein, sondern ob Ihre Software Brotli-Daten aus fremder Hand entpackt. Dieser Beitrag zeigt, wo das passiert, welche Stände sicher sind und wie Sie Ihre Systeme mit getesteten Einzeilern prüfen.
Das Wichtigste vorab
- Was: ein Schreibzugriff außerhalb eines Puffers im Brotli-Decoder von Google Brotli 1.0.3 bis 1.2.0,
CVE-2026-111497, genannt „Node2Shell“, auch „Broccoli2Shell“. - Bewertung: CVSS 4.0 9,2 durch Google als vergebende Stelle; Microsoft und Red Hat kommen nach CVSS 3.1 auf 8,1, Node.js stuft die Lücke als „High“ ein.
- Folge: Absturz, Auslesen von Prozessspeicher, im Labor auch Codeausführung, sobald die Anwendung präparierte Brotli-Daten entpackt.
- Lage: bis 26.10. keine Ausnutzung in freier Wildbahn bekannt, kein Eintrag im KEV-Katalog der CISA; ein öffentlicher Exploit wirkt nur gegen einen absichtlich geschwächten Build.
- Fix: Brotli 1.0.10, 1.1.1 oder 1.2.1; Node.js 22.23.4, 24.22.1 oder 26.12.1; Python Brotli 1.2.1 bzw. brotlicffi 1.2.1.0; .NET 8.0.33, 9.0.22 oder 10.0.14. Danach Prozesse neu starten und Images neu bauen.
Was ist passiert?
Der Fehler ist alt, die Veröffentlichung kam schnell. Nach Angaben von Aikido fand OpenAI die Lücke bereits im Februar 2026; die Korrektur landete damals im öffentlichen Brotli-Repository, ohne als Sicherheitsfix gekennzeichnet zu sein. Projekte mit eigener Kopie des Brotli-Codes haben sie deshalb nicht übernommen. Node.js nennt als Melder das Team OpenAI Codex Security (Khai Tran und Sylvie Mayer), den Fix haben Matteo Collina und Antoine du Hamel eingebaut.
- Februar 2026: Die Korrektur landet im Brotli-Quellcode, ohne Sicherheitskennzeichnung.
- 21.10.: Node.js veröffentlicht 22.23.4, 24.22.1 und 26.12.1 mit zehn Sicherheitskorrekturen, darunter diese. Google veröffentlicht Brotli 1.0.10, 1.1.1 und 1.2.1. Vercel schaltet WAF-Regeln, die offiziellen Node.js-Docker-Images werden aktualisiert.
- 22.10.: Die NVD veröffentlicht CVE-2026-111497, GitHub den Hinweis GHSA-9v8h-qqgm-4m35; Brotli 1.2.1 erscheint auf PyPI. Imperva zeigt Codeausführung auf dem offiziellen Image von Node.js 24.22.0 (Linux, arm64) und hält den Exploit zurück. Ein erster öffentlicher Proof of Concept erreicht Codeausführung nur gegen einen absichtlich geschwächten Build. Bun 1.4.4 erscheint.
- 23.10.: brotlicffi 1.2.1.0 erscheint, die Python-Pakete erhalten eigene Hinweise (PYSEC-2026-4322 und PYSEC-2026-4323). Envoy und Istio liefern Korrekturen.
- 24.10.: Es folgen das Ruby-Gem 0.9.1, die PHP-Erweiterung 0.21.1 und brotli4j 1.24.0 für Java; Amazon Linux 2023 veröffentlicht ALAS2023-2026-3334.
- 25.10.: Microsoft liefert außerplanmäßig .NET 8.0.33, 9.0.22 und 10.0.14 sowie .NET 11 RC3, laut SecurityWeek auch Updates für Visual Studio 2019, 2022 und 2026 sowie PowerShell 7.4 bis 7.6.
- 26.10.: Ubuntu veröffentlicht USN-8956-1 für 22.04 bis 26.10; Debian hat mit DSA-6582-1 (trixie) und DLA-4855-1 (bookworm) korrigierte Pakete.
Einordnung: Bis zum 26. Oktober ist keine Ausnutzung in freier Wildbahn bekannt. Die CISA hat die Lücke nicht in ihren KEV-Katalog aufgenommen; in ihrer Bewertung ist sie nicht automatisierbar, die technische Wirkung aber vollständig. Microsoft hält eine Ausnutzung für „wahrscheinlicher“ (Exploitation More Likely). Die NVD hat die Lücke noch nicht selbst bewertet, manche Scanner zeigen 9,8 nach CVSS 3.1. Die abweichenden Werte bilden ab, dass ein Angriff nur gelingt, wenn die Anwendung fremde Brotli-Daten entpackt. Wer das tut, sollte nicht auf den ersten Einbruch warten.
Die Lücke verständlich erklärt
Brotli komprimiert Daten in Blöcken und der Datenstrom darf zwischen Blocktypen wechseln. Die Funktion
DecodeBlockTypeAndLength() in c/dec/decode.c meldete bisher nur „hat geklappt“
oder „hat nicht geklappt“. Das zweite konnte zweierlei heißen: Die Eingabe ist noch nicht vollständig da,
oder der Strom verlangt einen Wechsel, den es nicht geben kann, etwa in einer Kategorie mit nur einem
Blocktyp.
Der streamende Decoder hielt beides für „mehr Eingabe nötig“ und hängte weitere Bytes an einen internen
Puffer von acht Byte an, auch über dessen Ende hinaus. Der schnelle Pfad ignorierte die Rückmeldung ganz und
decodierte aus einem unmöglichen Zustand weiter. Ein präparierter Datenstrom überschreibt so den
benachbarten Zustand des Decoders. Die Korrektur führt einen eigenen Fehlercode ein,
BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (-17), den jeder Aufrufer
zurückgibt. Fachlich sind das zwei Schwächen: eine ungeprüfte Rückgabe (CWE-252) und ein Schreiben
außerhalb eines Puffers (CWE-787).
Warum das so weit reicht: Brotli steckt hinter Content-Encoding: br in
Browsern, HTTP-Bibliotheken und Laufzeitumgebungen. Viele Projekte liefern den C-Code als eigene Kopie
mit, Node.js, .NET und die Python-Pakete von PyPI etwa. Eine solche Kopie erfasst das Update der
Distribution nicht; jede braucht ihr eigenes Update.
Drei Wege zum Decoder
Eine betroffene Brotli-Version auf der Platte ist noch kein Angriff. Gefährlich wird sie, wenn Daten aus fremder Hand den Decoder erreichen. Das geht auf drei Wegen:
Eingehend: der Server entpackt Anfragen
Ein Client schickt einen Body mit Content-Encoding: br und die Anwendung entpackt ihn vor
der Verarbeitung. Das tun Express 5.0.0 bis 5.3.0 bzw. body-parser 2.0.0 bis 2.3.0 mit
json(), raw(), text() und urlencoded(), ASP.NET Core
mit eingeschalteter Request-Decompression für br sowie Python-Frameworks mit entsprechender
Middleware. Ein nackter node:http-Server entpackt nichts von selbst; Express 4 und
body-parser 1.x kennen Brotli für Anfragen nicht. In .NET ist die Request-Decompression ab Werk
aus.
Ausgehend: die Anwendung lädt fremde Inhalte
Die Anwendung ruft eine URL ab und entpackt die Antwort automatisch. Das fetch() von Node.js
tut das ohne weiteres Zutun; urllib3 und damit requests sowie aiohttp und httpx tun es, sobald das
Python-Paket Brotli oder brotlicffi installiert ist; in .NET der HttpClient, wenn
AutomaticDecompression Brotli oder All enthält. Typische Auslöser sind Webhooks,
Link-Vorschauen, Crawler, „Import von URL“ und KI-Agenten, die Webseiten lesen. Eine Web Application
Firewall vor Ihrem Server sieht diese Antworten nicht. br aus dem Accept-Encoding
zu streichen hilft wenig, denn ein böswilliger Server schickt Brotli trotzdem.
Direkt: eigener Code entpackt Daten
Code, der zlib.brotliDecompress(), brotli.decompress() oder
BrotliStream auf Dateien, Caches oder Nachrichten aus einer Warteschlange anwendet, ist
betroffen, sobald diese Daten nicht aus vertrauenswürdiger Quelle stammen.
Aus unserer eigenen Inventur: Wie unbemerkt Brotli mitkommt, zeigt ein gängiges
Chat-Frontend für lokale Sprachmodelle. Im Image ghcr.io/open-webui/open-webui:v0.11.4-slim
fanden wir am 26.10. das Python-Paket Brotli 1.2.0 neben aiohttp, httpx und requests, dazu die
Systembibliothek libbrotli1 1.0.9-2+b6 auf Debian 12. Beides liegt im betroffenen
Bereich. Wie groß das Risiko ist, hängt davon ab, ob die Instanz fremde URLs abrufen darf, etwa für
Websuche oder das Laden von Webseiten. Unsere eigenen Dienste auf
python:3.14.7-slim-trixie mit reiner Standardbibliothek enthalten dagegen keinen
Brotli-Decoder.
Wer ist betroffen?
Betroffen ist jede Software, die den C-Decoder von Brotli 1.0.3 bis 1.2.0 lädt oder mitbringt. Die wichtigsten Fälle, Stand 26. Oktober 2026:
| Umgebung | Betroffen | Fixstand | Anmerkung |
|---|---|---|---|
| Node.js 22 · 24 · 26 | ja, Decoder in der Laufzeit | 22.23.4 · 24.22.1 · 26.12.1 | Node.js 20, 21, 23 und 25 erhalten keinen Fix. Die Node.js-Pakete von Ubuntu und Debian nutzen die Systembibliothek. |
| Bun | ja | 1.4.4 | über fetch(), node:zlib und DecompressionStream |
Python Brotli · brotlicffi | ja | 1.2.1 · 1.2.1.0 | wirkt über requests/urllib3, aiohttp, httpx[brotli], Scrapy; kommt oft als indirekte Abhängigkeit |
| .NET 8 · 9 · 10 | ja, ab Werk nicht erreichbar | 8.0.33 · 9.0.22 · 10.0.14 | .NET Framework nicht betroffen, .NET 7 ohne Fix; self-contained und NativeAOT neu veröffentlichen |
| Visual Studio · PowerShell | ja | Updates vom 25.10. | Visual Studio 2019, 2022, 2026; PowerShell 7.4, 7.5, 7.6 |
Systembibliothek libbrotli | ja | siehe nächste Tabelle | Programme, die sie laden, brauchen nach dem Update einen Neustart |
| Envoy · Istio | mit Brotli-Decompressor-Filter | Envoy 1.40.0, 1.39.3, 1.38.6, 1.37.8; Istio 1.29.9, 1.30.6, 1.31.2 | bis zum Update den Filter aus den EnvoyFilters entfernen |
| Java | nur JNI-Hüllen um den C-Code | brotli4j 1.24.0 | reine Java-Portierungen nicht betroffen |
| PHP · Ruby | Erweiterung bzw. Gem | PHP-Erweiterung brotli 0.21.1 · Gem 0.9.1 | mitgelieferte Kopien in anderen Projekten bleiben betroffen, bis sie aktualisiert sind |
| Go · Rust | Go-Portierung nur Absturz, Rust fängt den Fall ab | andybalholm/brotli seit 23.10. | cgo-Bindings um den C-Code sind betroffen |
Apache mod_brotli | nein | nicht nötig | komprimiert nur, entpackt nicht |
| Chromium · Firefox | korrigiert | laut broccoli2shell.com | Browser regulär aktualisieren |
| DuckDB, Apache Arrow, 7-Zip-zstd, p7zip, EDK II | ja | noch offen | laut der Übersicht auf broccoli2shell.com, Stand 26.10. |
Falle: das falsche Update. npm update brotli oder ein neues Express
ändern nichts, denn der verwundbare Code steckt in der Node.js-Laufzeit. apt upgrade auf
dem Host schließt keine Lücke in einem Container-Image, das seine eigene Laufzeit mitbringt; ein Image auf
node:24.22.0 bleibt verwundbar, bis es neu gebaut ist. Laufende Prozesse behalten den alten
Decoder im Speicher, bis sie neu starten. Und process.versions.brotli taugt nicht als Beleg:
Node.js hat den Fix eingepflegt, die angezeigte Brotli-Version ändert sich dadurch nicht zwingend.
Maßgeblich ist die Node.js-Version.
Sichere Versionen
Die Fixstände der Systembibliothek und der Laufzeiten, Stand 26. Oktober 2026. Vergleichen Sie mit der Paketversion Ihrer Quelle:
| Quelle | Paket | Fixstand | Hinweis |
|---|---|---|---|
| Google Brotli (upstream) | 1.0 · 1.1 · 1.2 | 1.0.10 · 1.1.1 · 1.2.1 | Korrektur ab Commit 0ed4268 |
| Ubuntu 26.10 | brotli, libbrotli1, python3-brotli | 1.2.0-4ubuntu0.1 | USN-8956-1 |
| Ubuntu 26.04 LTS | wie oben | 1.2.0-3ubuntu0.1 | USN-8956-1 |
| Ubuntu 24.04 LTS | wie oben | 1.1.0-2ubuntu0.1 | USN-8956-1 |
| Ubuntu 22.04 LTS | wie oben | 1.0.9-2ubuntu0.1 | USN-8956-1 |
| Debian 13 trixie | brotli | 1.1.0-2+deb13u1 | DSA-6582-1 |
| Debian 12 bookworm | brotli | 1.0.9-2+deb12u1 | DLA-4855-1 (Debian LTS) |
| Alpine | brotli | 1.2.1-r0 (edge, 3.23, 3.24) · 1.1.1-r0 (3.21, 3.22) | laut Aikido |
| Amazon Linux 2023 | brotli | 1.1.0-1.amzn2023.0.2 | ALAS2023-2026-3334 |
| RHEL 8 · 9 · 10 | brotli | teilweise | Red Hat: „Important“, CVSS 3.1 8,1; Bulletin RHSB-2026-015 |
| Fedora 43 bis 45 · SUSE | brotli | noch offen | laut Aikido am 26.10. |
| Node.js (offizielle Builds) | 22 · 24 · 26 | 22.23.4 · 24.22.1 · 26.12.1 | auch die offiziellen Docker-Images seit 21.10. |
| Python (PyPI) | Brotli · brotlicffi | 1.2.1 · 1.2.1.0 | PYSEC-2026-4322, PYSEC-2026-4323 |
| .NET Runtime | 8 · 9 · 10 | 8.0.33 · 9.0.22 · 10.0.14 | SDKs 8.0.133/8.0.427, 9.0.123/9.0.320, 10.0.114/10.0.403 |
1.Bestand prüfen
Beginnen Sie mit den Systemen, die fremde URLs abrufen oder komprimierte Anfragen annehmen. Jeder der
folgenden Befehle gibt ein fertiges Ergebnis aus, je Fundstelle OK, VULNERABLE
oder einen Hinweis. Wir haben alle gegen echte Images getestet; ein älteres node:22-alpine
meldete etwa v22.23.3 VULNERABLE.
node -e 'const v=process.versions.node.split(".").map(Number),f={22:[23,4],24:[22,1],26:[12,1]}[v[0]];console.log(process.version,!f?"NO FIX (end of life)":(v[1]>f[0]||(v[1]==f[0]&&v[2]>=f[1]))?"OK":"VULNERABLE")'
# same check inside an image: docker run --rm --entrypoint node <image> -e '...'
python3 - <<'EOF'
from importlib.metadata import version, PackageNotFoundError
fixed = {"Brotli": (1, 2, 1), "brotlicffi": (1, 2, 1, 0)}
for name, good in fixed.items():
try:
v = version(name)
except PackageNotFoundError:
print(name, "not installed")
continue
parts = tuple(int(p) for p in v.split(".")[:len(good)] if p.isdigit())
print(name, v, "OK" if parts >= good else "VULNERABLE")
EOF
# inside a container: docker exec -i <container> python3 - <<'EOF' ... EOF
Die Systembibliothek prüfen Sie auf Debian und Ubuntu gegen den Fixstand Ihrer Version aus der Tabelle,
hier für Debian 12. Der zweite Befehl zählt die Prozesse, die noch eine ersetzte
libbrotlidec im Speicher halten; bei 0 ist alles neu geladen:
dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\n' 'libbrotli1*' 2>/dev/null \
| awk '$1=="ii"{r=system("dpkg --compare-versions "$3" ge 1.0.9-2+deb12u1"); print $2, $3, (r==0?"OK":"VULNERABLE")}'
sudo grep -ls 'libbrotlidec.*(deleted)' /proc/[0-9]*/maps 2>/dev/null | wc -l
Für .NET zählt die gemeinsame Laufzeit Microsoft.NETCore.App, die auch eine
ASP.NET-Core-Anwendung unter IIS lädt. Unter Windows und Linux:
$fix = @{8=33; 9=22; 10=14}; dotnet --list-runtimes | ForEach-Object { if ($_ -match '^Microsoft\.NETCore\.App (\d+)\.(\d+)\.(\d+)') { $maj = [int]$Matches[1]; $p = [int]$Matches[3]; $s = if ($maj -lt 8) { 'NO FIX (end of life)' } elseif (-not $fix.ContainsKey($maj)) { 'CHECK' } elseif ($p -ge $fix[$maj]) { 'OK' } else { 'VULNERABLE' }; "Microsoft.NETCore.App $($Matches[1]).$($Matches[2]).$p $s" } }
dotnet --list-runtimes | awk '$1=="Microsoft.NETCore.App"{split($2,v,".");f=(v[1]==8?33:v[1]==9?22:v[1]==10?14:-1);print $1,$2,(v[1]<8?"NO FIX (end of life)":f<0?"CHECK":(v[3]+0>=f?"OK":"VULNERABLE"))}'
Ob Ihr eigener Code Brotli aus fremder Hand entpackt, zeigt eine Suche im Quelltext. Treffer sind keine Lücke, sondern die Stellen, die Sie zuerst ansehen:
# .NET: request decompression, HttpClient decompression, direct decoder use
grep -rnE --include='*.cs' 'AddRequestDecompression|DecompressionMethods\.(All|Brotli)|BrotliStream|BrotliDecoder' .
# Node.js: direct decoder calls, and Express 5 / body-parser 2 in the dependency tree
grep -rnE --include='*.js' --include='*.ts' --exclude-dir=node_modules 'brotliDecompress|createBrotliDecompress' .
npm ls express body-parser --all 2>/dev/null | grep -cE 'express@5|body-parser@2'
2.Patchen, neu starten, neu bauen
Die Reihenfolge ist immer dieselbe: aktualisieren, laufende Prozesse neu starten, Images neu bauen. Wer den zweiten oder dritten Schritt auslässt, hat den alten Decoder weiter im Betrieb.
sudo apt update
sudo apt install --only-upgrade libbrotli1 brotli python3-brotli # skips what is not installed
# restart the services that still map the old library, until this prints 0
sudo grep -ls 'libbrotlidec.*(deleted)' /proc/[0-9]*/maps 2>/dev/null | wc -l
python3 -m pip install -U "Brotli>=1.2.1"
python3 -m pip install -U "brotlicffi>=1.2.1.0"
# then regenerate lockfiles (requirements.txt, poetry.lock, uv.lock) and rebuild images
- Node.js: auf 22.23.4, 24.22.1 oder 26.12.1 wechseln, alle Node.js-Prozesse neu starten. Images, die auf einen festen Tag wie
node:24.22.0zeigen, auf den korrigierten Tag umstellen und neu bauen; das gilt auch für Single Executable Applications und Startup-Snapshots. Node.js 20, 21, 23 und 25 bekommen keinen Fix: auf 22 oder 24 wechseln. - .NET unter IIS: das Hosting Bundle bzw. die Laufzeit 8.0.33, 9.0.22 oder 10.0.14 installieren und die Anwendungspools neu starten, etwa mit
Restart-WebAppPool -Name <pool>oderiisreset. Self-contained Anwendungen mit dem aktualisierten SDK neu veröffentlichen; bei NativeAOT ersetzt ein Update der Laufzeit auf dem Server den eingebauten Decoder nicht. - .NET in Containern: die Images von
mcr.microsoft.com/dotnetneu ziehen und die Anwendung neu bauen. - Container allgemein: Ein Update auf dem Host erreicht das Image nicht. Jedes Image mit eigener Laufzeit oder eigenem
libbrotliauf gepatchter Basis neu bauen und neu ausrollen; bei Images mit fester Digest-Pinnung den Pin bewusst nachziehen.
3.Notbehelf bis zum Patch
Bis das Update läuft, helfen Sperren an zwei Stellen. Sie ersetzen das Update nicht; Microsoft und Imperva betonen das ausdrücklich. Testen Sie jede Sperre, denn sie verändert die Behandlung von Anfragen und Antworten.
Eingehend: Brotli-Bodies am Proxy ablehnen
# nginx (server or location block): reject Brotli request bodies before the app decodes them
if ($http_content_encoding ~* "br") { return 415; }
# HAProxy (frontend)
http-request deny deny_status 415 if { req.hdr(content-encoding) -m sub -i br }
<system.webServer>
<security>
<requestFiltering>
<filteringRules>
<!-- CVE-2026-111497: reject Brotli request bodies, logged as 404.19 -->
<filteringRule name="Block Brotli request bodies" scanUrl="false" scanQueryString="false" scanAllRaw="false">
<scanHeaders>
<add requestHeader="Content-Encoding" />
</scanHeaders>
<denyStrings>
<add string="br" />
</denyStrings>
</filteringRule>
</filteringRules>
</requestFiltering>
</security>
</system.webServer>
In der Anwendung: Brotli aus bestehender Konfiguration entfernen
Microsoft empfiehlt, Brotli nur dort zu entfernen, wo die Dekomprimierung bereits eingeschaltet ist, und keine neuen Dekomprimierungsfunktionen hinzuzufügen:
// only where AddRequestDecompression is already configured
builder.Services.AddRequestDecompression(options =>
{
// CVE-2026-111497: stop decoding Brotli request bodies until the runtime is patched
options.DecompressionProviders.Remove("br");
});
// HttpClient: was DecompressionMethods.All, drop Brotli until patched
var handler = new SocketsHttpHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
- Python:
python3 -m pip uninstall -y Brotli brotlicffiund Extras wiehttpx[brotli]entfernen, danach die Lockfiles neu erzeugen. requests, aiohttp und httpx fallen dann auf gzip und deflate zurück. Andere mitgelieferte Brotli-Kopien bleiben davon unberührt. - Node.js: Für Antworten auf
fetch()gibt es keinen Notbehelf, nur das Update. Eingehend hilft die Sperre am Proxy. - curl:
--compressedaus Skripten und.curlrcentfernen;curl -Vzeigt, ob curl mit Brotli gebaut ist. - Envoy und Istio: den Brotli-Decompressor-Filter entfernen, bis die Proxys aktualisiert sind.
- Ausgehende Abrufe begrenzen: Dienste, die fremde URLs laden, nur über eine Egress-Freigabeliste ins Internet lassen. Das senkt das Risiko für Webhooks, Vorschauen und KI-Agenten deutlich.
4.Woran man Angriffe erkennt
Ein Angriff über den ausgehenden Weg hinterlässt in Ihren Zugriffs-Logs keine Spur, denn die schädliche Antwort kommt vom fremden Server. Hier helfen nur Logs der ausgehenden Verbindungen und die Absturzmeldungen des Dienstes. Die Spuren im Überblick:
| Spur | Woran Sie sie erkennen | Aussagekraft |
|---|---|---|
Fehlercode -17 | BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH in den Logs eines gepatchten Dienstes | Jemand hat einen Datenstrom genau dieser Form geschickt |
Fehlercode -9 | Derselbe Strom scheitert bei einem ungepatchten Decoder später an der Blocklänge (laut Bun-Issue 46352) | Hinweis; auch beschädigte Daten lösen ihn aus |
| Abstürze beim Entpacken | Segmentation Fault, unerwartete Prozessenden, Neustarts des Dienstes während der Dekomprimierung | allein kein verlässlicher Beleg, aber ein Grund zur Prüfung |
| Auffällige Anfragen | Content-Encoding: br an Endpunkten, die nie komprimierte Bodies erwarten; IIS-Status 404.19 nach dem Notbehelf | Versuch; nur sichtbar, wo Proxy oder Webserver den Header protokollieren |
| Folgen einer Codeausführung | fremde Prozesse unter dem Dienstkonto, neue Dateien, Cron-Einträge, systemd-Units, SSH-Schlüssel | starkes Zeichen für einen Einbruch |
Bei einem Verdacht: den Dienst isolieren, Logs und Absturzberichte sichern, alle Geheimnisse wechseln, die der Prozess lesen konnte, und das System aus einem sauberen Image neu aufsetzen. Weil die Lücke auch Speicherinhalte preisgeben kann, gilt das für Schlüssel und Tokens vorsorglich auch ohne Hinweis auf Codeausführung. Als Verantwortlicher melden Sie eine Verletzung des Schutzes personenbezogener Daten binnen 72 Stunden (Art. 33 DSGVO); Einrichtungen unter NIS2 haben eigene Meldepflichten.
Häufige Fragen
Was ist Node2Shell?
Node2Shell, auch Broccoli2Shell genannt, ist der Spitzname für CVE-2026-111497, einen Schreibfehler außerhalb eines Puffers im Brotli-Decoder von Google Brotli 1.0.3 bis 1.2.0. Ein präparierter Brotli-Datenstrom kann den Speicher des Decoders beschädigen; die Folgen reichen vom Absturz über das Auslesen von Speicher bis zur Codeausführung, die Imperva im Labor auf Node.js 24.22.0 gezeigt hat. Node.js hat die Lücke am 21. Oktober 2026 geschlossen, Google bewertet sie mit CVSS 4.0 9,2.
Bin ich betroffen, wenn ich kein Node.js einsetze?
Möglicherweise ja, denn der Fehler sitzt in der Brotli-Bibliothek selbst. Betroffen sind auch die Python-Pakete Brotli und brotlicffi, die über requests, aiohttp und httpx wirken, .NET 8, 9 und 10, Bun, Envoy mit Brotli-Filter, die Systembibliothek libbrotli der Linux-Distributionen und Programme mit eigener Kopie des C-Codes. Entscheidend ist, ob Ihre Software Brotli-Daten aus fremder Hand entpackt.
Reicht es, das npm-Paket brotli oder Express zu aktualisieren?
Nein. Node.js bringt den Brotli-Decoder in der Laufzeit mit; nur eine korrigierte Laufzeit hilft, also Node.js 22.23.4, 24.22.1 oder 26.12.1. Express 5 und body-parser 2 sind ein Weg zum Fehler, aber kein Ort der Korrektur. Danach müssen alle Node.js-Prozesse neu starten und Container-Images neu gebaut werden.
Sind .NET Framework, IIS und ASP.NET Core betroffen?
Microsoft nennt .NET Framework ausdrücklich als nicht betroffen. Betroffen sind .NET 8, 9 und 10 vor 8.0.33, 9.0.22 und 10.0.14 auf allen Plattformen, also auch ASP.NET Core unter IIS. Ab Werk ist die Lücke dort aber nicht erreichbar: Gefährlich wird es erst mit Request-Decompression für br, mit automatischer Dekomprimierung im HttpClient, die Brotli einschließt, oder mit direktem Einsatz von BrotliStream und BrotliDecoder. IIS selbst erwähnt Microsofts Hinweis nicht.
Wird Node2Shell schon ausgenutzt?
Bis zum 26. Oktober 2026 ist keine Ausnutzung in freier Wildbahn bekannt, die CISA führt die Lücke nicht in ihrem KEV-Katalog. Imperva hat Codeausführung im Labor gezeigt, den Exploit aber nicht veröffentlicht; ein öffentlicher Proof of Concept wirkt nur gegen einen absichtlich geschwächten Build. Microsoft stuft eine Ausnutzung als wahrscheinlicher ein.
Was hilft, wenn ich nicht sofort patchen kann?
Für eingehende Anfragen hilft es, Bodies mit Content-Encoding br am Proxy oder Load Balancer abzulehnen, bevor die Anwendung sie entpackt. In .NET entfernen Sie Brotli aus einer bestehenden Request-Decompression und aus AutomaticDecompression, in Python deinstallieren Sie vorübergehend Brotli und brotlicffi. Für fetch() in Node.js gibt es keinen Notbehelf; dort hilft nur das Update.
Quellen
Externe Quellen, Stand 26. Oktober 2026 (öffnen in einem neuen Tab):
- Node.js, October 2026 Security Releases
- NVD, CVE-2026-111497
- CVE.org, CVE-2026-111497
- GitHub Advisory Database, GHSA-9v8h-qqgm-4m35
- Google Brotli, Release 1.2.1
- Google Brotli, Commit 0ed4268
- Microsoft, Security Advisory CVE-2026-111497 für .NET
- .NET Blog, Out-of-Band-Updates vom 25. Oktober 2026
- Imperva, Node2Shell: From Brotli Data to Remote Code Execution
- Aikido, Python-Pakete und weitere Ökosysteme
- OpenSourceMalware, Node2Shell betrifft Python
- Hadrian, What we know about the Node.js Brotli RCE
- broccoli2shell.com, Übersicht betroffener Projekte
- OSV, PYSEC-2026-4322 (Brotli)
- Ubuntu, USN-8956-1
- Debian Security Tracker, CVE-2026-111497
- Red Hat, CVE-2026-111497
- Amazon Linux, ALAS2023-2026-3334
- Vercel, Node.js Security Advisory
- SecurityWeek, Patches bei Microsoft, Node.js und Python
- Microsoft Learn, IIS Request Filtering Rules
Bestand prüfen, patchen, Images neu bauen
Sie betreiben Node.js-, Python- oder .NET-Dienste und wollen wissen, wo bei Ihnen Brotli aus fremder Hand entpackt wird? Wir prüfen Ihre Server und Container-Images, spielen die Korrekturen ein und begrenzen die Wege dorthin, herstellerunabhängig und DSGVO-konform, mit Rechenzentren in Deutschland und Finnland.
Dieser Beitrag dient der allgemeinen Information und ersetzt keine Prüfung im Einzelfall. Versionsstände und Befehle beziehen sich auf den genannten Stand und sind an Ihre Umgebung anzupassen. Stand: Oktober 2026.