ISW-Tools
Jörn Walter Veröffentlicht 8 Min. Lesezeit Allgemein
Der Windows Papst · Security · 29.10.2026

Node2Shell (CVE-2026-111497): Node.js-Lücke im Brotli-Decoder – so finden und patchen Sie jede node.exe im Netz

Am 21. Oktober 2026 hat das Node.js-Projekt für alle unterstützten Release-Linien zehn Sicherheitslücken geschlossen. Die gefährlichste davon – „Node2Shell“ – erlaubt über manipulierte Brotli-Daten Speicherkorruption bis hin zur Codeausführung, ohne Anmeldung. Ein öffentlicher Proof of Concept existiert bereits. Wer Node.js auf Windows-Servern betreibt, oft ohne es zu wissen, sollte jetzt inventarisieren und aktualisieren.

Was ist passiert?

Node.js bringt eine eigene Kopie der Brotli-Bibliothek mit, über die das Modul node:zlib Brotli-Daten entpackt. Ein ungültiger Blockwechsel im Datenstrom wurde vom Decoder nicht als Formatfehler gewertet, sondern als „es fehlen noch Daten“. Der Streaming-Decoder hängte deshalb weiter Bytes an einen internen Puffer von nur acht Byte an – und schrieb über dessen Ende hinaus. Die Folge reicht vom Absturz des Prozesses über das Auslesen von Prozessspeicher bis zur Ausführung von Code mit den Rechten des Node-Prozesses.

Node.js selbst stuft die Lücke als „High“ ein, im CVE-Eintrag steht ein CVSS-Wert von 9.2 (kritisch). Akamai, das der Lücke den Namen Node2Shell gegeben hat, sieht laut eigener Telemetrie in rund 61 % der beobachteten Netzwerke noch betroffene Node.js-Versionen. Das HKCERT meldet zudem, dass Exploit-Code öffentlich verfügbar ist.

Wichtig: Es gibt laut Node.js-Advisory keinen Workaround, der die Lücke vollständig schließt. Die einzige vollständige Abhilfe ist das Update auf 22.23.4, 24.22.1 oder 26.12.1 – und der anschließende Neustart aller Node-Prozesse.

Wann ist eine Anwendung angreifbar?

Ein nackter http-Server von Node.js entpackt eingehende Brotli-Daten nicht von sich aus. Das klingt beruhigend – ist es aber nicht, denn die Daten erreichen den Decoder auf mehreren Wegen, ohne dass der Entwickler die Brotli-API je direkt aufgerufen hat:

  • Direkter Aufruf: Anwendungen, die nicht vertrauenswürdige Eingaben an zlib.brotliDecompress() oder zlib.createBrotliDecompress() übergeben.
  • Eingebautes fetch(): entpackt Brotli-kodierte Antworten automatisch. Ein bösartiger oder kompromittierter Server kann so den Client angreifen – relevant für jedes Skript, jeden Agenten und jeden Dienst, der externe APIs abfragt.
  • Express 5 / body-parser 2: Die Parser für JSON, Raw, Text und URL-encoded entpacken Request-Bodies mit Content-Encoding: br standardmäßig, weil die Option inflate auf true steht. Damit kann jeder Client, der die API erreicht, angreifen.

Alle zehn Lücken im Überblick

CVE Stufe Bereich / Auswirkung Linien
CVE-2026-111497 High Brotli-Decoder: Out-of-bounds-Write bis RCE (Node2Shell) 26, 24, 22
CVE-2026-105482 High dns.resolve*() kürzt Namen am NUL-Zeichen – Allowlist-Prüfungen laufen ins Leere 26, 24, 22
CVE-2026-105483 High TLS-Hostnamenprüfung umgehbar bei IP in Vollbreiten-Ziffern 26, 24
CVE-2026-106069 High TLS-Hostnamenprüfung umgehbar bei IPv4 mit führender Null (oktal vs. dezimal) 26, 24, 22
CVE-2026-105481 Medium HTTP Keep-Alive: vorab gesendete Antwort wird dem nächsten Request zugeordnet 26, 24, 22
CVE-2026-106072 Medium DNS-SAN authentifiziert IP-Endpunkt bei nicht-kanonischer IPv4-Schreibweise 26, 24, 22
CVE-2026-106074 Medium randomUUID()/randomInt() wiederholen Werte in Snapshots und SEAs 26, 24, 22
CVE-2026-106070 Low zlib.ZipFile liefert nach fehlgeschlagener Header-Prüfung fremde Bytes 26
CVE-2026-106071 Low Permission Model: zu weit gefasste Wildcard-Freigaben 26
CVE-2026-106073 Low Permission Model: fs.realpathSync() ohne Leseprüfung 26, 24, 22

Zusätzlich aktualisiert das Release mitgelieferte Abhängigkeiten: c-ares und Undici in allen Linien, OpenSSL in 24.x und 22.x, SQLite in 22.x sowie die Root-Zertifikate – unter anderem wegen der Kompromittierung einer Zwischen-CA von eMudhra.

Für Admins besonders relevant: Die drei TLS-Lücken treffen genau die Fälle, die im internen Netz häufig vorkommen – Dienste, Agenten und Skripte, die Server per IP-Adresse statt per FQDN ansprechen. Wer interne Zertifikate mit IP-Adressen als DNS-SAN ausgestellt hat, sollte die Vorlagen bei dieser Gelegenheit gleich mit prüfen.

Betroffene und gepatchte Versionen

Release-Linie Verwundbar bis Gepatcht ab
Node.js 26.x kleiner 26.12.1 26.12.1
Node.js 24.x kleiner 24.22.1 24.22.1
Node.js 22.x kleiner 22.23.4 22.23.4
25.x, 23.x, 20.x und älter alle Versionen kein Fix – End of Life, migrieren

Schritt 1: Jede node.exe im Netz finden

Das eigentliche Problem auf Windows-Servern ist selten das Patchen, sondern das Finden. Node.js steckt nicht nur unter C:\Program Files\nodejs, sondern auch in Versionsmanagern wie nvm-windows, in Build-Agenten, in Container-Images und als mitgelieferte node.exe in Anwendungen von Drittherstellern. Ein Blick in „Programme und Features“ reicht deshalb nicht.

Das folgende Skript sucht laufende Node-Prozesse und node.exe-Dateien in den üblichen Ablageorten, liest die Version aus und bewertet sie gegen die Fixstände vom 21.10.2026:

$scan = {
# Fixstände Node.js Security Release 21.10.2026
$fixed = @{ 22 = [version]'22.23.4'; 24 = [version]'24.22.1'; 26 = [version]'26.12.1' }

$running = @(Get-Process node -ErrorAction SilentlyContinue)
$paths = @($running | Select-Object -ExpandProperty Path)
$paths += Get-ChildItem -Path 'C:\Program Files','C:\Program Files (x86)','C:\ProgramData','C:\Users' `
-Filter node.exe -Recurse -File -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty FullName

foreach ($p in ($paths | Where-Object { $_ } | Sort-Object -Unique)) {
$raw = (Get-Item $p).VersionInfo.ProductVersion
if (-not $raw) { $raw = (& $p --version) }
$v = [version](($raw -replace '^v','') -replace '[^\d\.].*$','')

$status = if ($v.Major -gt 26) { 'NEUERE LINIE - pruefen' }
elseif (-not $fixed.ContainsKey($v.Major)) { 'EOL - MIGRIEREN' }
elseif ($v -lt $fixed[$v.Major]) { 'VERWUNDBAR' }
else { 'GEPATCHT' }

[pscustomobject]@{
Version = $v
Status = $status
Laeuft = [bool]($running | Where-Object Path -eq $p)
Pfad = $p
}
}
}

# Lokal ausführen
& $scan | Format-Table -AutoSize

Für alle Server der Domäne per WinRM:

$server = Get-ADComputer -Filter 'OperatingSystem -like "*Server*" -and Enabled -eq $true' |
Select-Object -ExpandProperty DNSHostName

Invoke-Command -ComputerName $server -ScriptBlock $scan -ErrorAction SilentlyContinue |
Select-Object PSComputerName, Version, Status, Laeuft, Pfad |
Sort-Object Status, PSComputerName |
Export-Csv -Path .\node-inventar.csv -NoTypeInformation -Encoding UTF8 -Delimiter ';'

Die rekursive Suche unter C:\Users kann auf Terminalservern dauern – dort lässt sich der Pfad bei Bedarf herausnehmen. Wer zusätzlich wissen will, welche Node-Prozesse aus dem Netz erreichbar sind:

Get-NetTCPConnection -State Listen |
Where-Object { (Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName -eq 'node' } |
Where-Object { $_.LocalAddress -notin '127.0.0.1','::1' } |
Select-Object LocalAddress, LocalPort, OwningProcess

Schritt 2: Aktualisieren

Installation per MSI oder winget

# LTS-Paket
winget upgrade --id OpenJS.NodeJS.LTS --exact --silent

# Kontrolle
node --version

nvm-windows

nvm install 24.22.1
nvm use 24.22.1
nvm list # alte Versionen danach mit "nvm uninstall" entfernen

Container und Drittanbieter-Software

Container-Images auf einem gepatchten Basis-Image neu bauen und neu ausrollen – gepinnte Tags wie node:24.14.0 aktualisieren sich nicht von selbst. Bei Herstellerprodukten mit eigener node.exe hilft nur das Update des Herstellers; die Datei nicht eigenmächtig austauschen, sonst droht der Verlust des Supports. Bis dahin den Zugriff auf den Dienst per Firewall auf die nötigen Quellen begrenzen.

Überbrückung, solange nicht gepatcht werden kann

Für Express-5-Anwendungen, die keine komprimierten Request-Bodies brauchen, lässt sich der serverseitige Angriffsweg schließen. Komprimierte Bodies werden dann mit HTTP 415 abgewiesen:

app.use(express.json({ inflate: false }));
app.use(express.urlencoded({ extended: true, inflate: false }));
app.use(express.text({ inflate: false }));
app.use(express.raw({ inflate: false }));

Den Client-Weg über fetch() deckt das nicht ab. Hier hilft nur, ausgehende Verbindungen der betroffenen Systeme auf bekannte Ziele zu beschränken und eingehende Zugriffe zu segmentieren. Das ist Schadensbegrenzung – kein Ersatz für das Update.

Fallstricke aus der Praxis

  • Neustart vergessen: Ein laufender Node-Prozess nutzt weiter die alte Binärdatei im Speicher. Dienste (NSSM, PM2, eigene Service-Wrapper, IIS mit iisnode) nach dem Update neu starten – die Spalte Laeuft im Skript zeigt, welche Pfade aktiv sind.
  • node --version lügt nicht, sagt aber nur die halbe Wahrheit: Es meldet die Version, die im PATH zuerst gefunden wird. Ein Dienst kann mit einem absoluten Pfad auf eine ältere Installation zeigen.
  • End-of-Life-Linien: Node.js 20 ist seit dem 30.04.2026 ohne Support, 23.x und 25.x ebenfalls. Dafür gibt es keinen Patch – hier steht eine Migration auf 22, 24 oder 26 an.
  • Mehrere Versionen parallel: Versionsmanager hinterlassen oft ein halbes Dutzend Node-Versionen pro Server. Nicht benötigte Versionen entfernen, sonst taucht der Befund beim nächsten Scan wieder auf.
  • Linux-Distributionspakete und Bun: Distributions-Builds bekommen den Fix über die Paketpflege des Herstellers, nicht über nodejs.org. Akamai weist außerdem darauf hin, auch Bun-Installationen zu prüfen.

Compliance-Bezug

Eine öffentlich ausnutzbare Lücke mit Exploit-Code ist ein klassischer Fall für das Schwachstellenmanagement. Im BSI IT-Grundschutz greift der Baustein OPS.1.1.3 Patch- und Änderungsmanagement, für NIS2-pflichtige Einrichtungen Art. 21 Abs. 2 lit. e (Umgang mit und Offenlegung von Schwachstellen bei Erwerb, Entwicklung und Wartung). Im CIS-Kontext ist es Control 7 – Continuous Vulnerability Management. Für den Nachweis zählt nicht nur das Update selbst, sondern das dokumentierte Inventar davor und die Prüfung danach – die CSV aus dem Skript oben eignet sich genau dafür.

Fazit

Node2Shell ist kein Problem nur für Webentwickler. Node.js läuft auf vielen Windows-Servern im Hintergrund – als Agent, als Build-Werkzeug, als Teil einer Fachanwendung. Wer jetzt systematisch inventarisiert, auf 22.23.4, 24.22.1 oder 26.12.1 aktualisiert, die Prozesse neu startet und End-of-Life-Versionen aussortiert, hat das Thema in einem Wartungsfenster erledigt. Wer wartet, verlässt sich darauf, dass niemand den öffentlichen Exploit-Code ausprobiert.

Passende ISW-Tools

CVE Scanner – NIST Database – gleicht installierte Software auf Windows-Systemen gegen die NIST NVD ab und zeigt bekannte CVEs.

Security Advisory Dashboard – Triage der BSI-CERT-Bund-Meldungen mit CISA KEV und EPSS, inklusive Asset-Überwachung.

Network Communication Monitor – zeigt prozessgenau, welche Dienste lauschen und mit wem sie sprechen.

App Service Manager – betreibt Node.js-Server als Windows-Dienst; nach dem Update den Dienst gezielt neu starten.

Windows Firewall Manager Pro – Zugriffe auf Node-Dienste zentral einschränken, solange nicht gepatcht ist.

Quellen: Node.js Project – Wednesday, October 21, 2026 Security Releases (nodejs.org); Akamai Security Intelligence Group – Inside Node2Shell: A Closer Look at CVE-2026-111497 (26.10.2026); HKCERT – Node.js Multiple Vulnerabilities (aktualisiert 26.10.2026); Vercel – Node.js security advisory: Brotli decoder RCE (CVE-2026-111497).

Porträt Jörn Walter

Jörn Walter

Inhaber von IT-Service Walter in Euskirchen, betreut Windows-Umgebungen von Unternehmen und entwickelt die ISW-ADTools.

Alle Beiträge von Jörn Walter