Am 4. August 2026 traf ein ausgeklügelter Angriff auf die Software-Lieferkette namens „ChainDrop“ das npm-Ökosystem , nachdem das GitHub-Konto eines Betreuers der weit verbreiteten Open-Source-Pakete „Keyv“ und „Cacheable“ kompromittiert worden war . Der daraus resultierende, sich selbst verbreitende Wurm breitete sich auf über 2.251 Versionen von 452 verschiedenen Paketen mit monatlich rund 2 Milliarden Downloads aus und betraf Unternehmen wie Deliveroo, Ornikar, OneReach, Picsart, Qlik und ServiceTitan.
„Keyv“ ist ein einfacher Schlüssel-Wert-Speicher für Node.js mit Unterstützung für mehrere Backends, während „Cacheable“ das zugrunde liegende HTTP-Cache-Framework darstellt. Zusammen dienen diese Pakete als grundlegende Caching-Infrastruktur im gesamten JavaScript-Ökosystem. Beide Pakete werden von demselben Entwickler gepflegt, dessen GitHub-Konto vom Angreifer kompromittiert wurde.
Der Angreifer veröffentlichte die erste schädliche Version, „keyv@6.0.0“, am 4. August 2026 gegen 9:00 Uhr UTC. Die Malware ist ein Ableger der „Mini“-Shai-Hulud-Familie; eine Zuordnung zu TeamPCP ist bislang unbestätigt. Der Wurm verbreitete sich rasch, indem er npm- und GitHub-Tokens aus kompromittierten Umgebungen sammelte und diese nutzte, um weitere manipulierte Versionen zu veröffentlichen. Socket identifizierte 2 .251 manipulierte Versionen in 452 Paketen.
Die Payload stiehlt eine umfassende Bandbreite sensibler Daten, darunter Cloud-Anmeldedaten, CI/CD-Geheimnisse, Entwickler-Token, KI-Konfigurationsdateien und Kryptowährungs-Wallets .Außerdem platziert sie Claude-Code- und Visual-Studio-Code-Hooks für eine dauerhafte Ausführung innerhalb der IDE. Zum Zeitpunkt der Erstellung dieses Artikels wurden dieser Kampagne noch keine CVE-Kennungen zugewiesen.
Erster Zugriff
Der Angreifer kompromittierte das GitHub-Konto des Keyv-Betreuers und verschaffte sich so direkten Push-Zugriff auf die Quellcode-Repositorys für Keyv, Cacheable, cache-manager, flat-cache, file-entry-cache sowie zahlreiche verwandte Pakete innerhalb des Monorepos des Betreuers.
Böswillige Veröffentlichung
Ab 9:00 Uhr UTC fügte der Angreifer dem Keyv-Repository Persistenz-Payloads für IDEs hinzu und veröffentlichte anschließend „keyv@6.0.0“ sowie nachfolgende bösartige Versionen. Da die Pakete über ihre legitimen GitHub-Actions-Workflows erstellt und veröffentlicht wurden , enthielten die kompromittierten Releases gültige SLSA-Herkunftsinformationen, wodurch die Kontrollen zur Integritätsprüfung umgangen wurden. Jedes manipulierte Paket enthielt in seiner `package.json` einen Eintrag „preinstall“: „node setup.mjs“, wodurch der Dropper automatisch ausgeführt wurde, bevor ein `npm install` abgeschlossen war.
Verbreitung des Wurms
Die Fähigkeit der Malware zur Selbstverbreitung ermöglichte es ihr, Pakete anderer Betreuerzu infizieren , deren Projekte von einem zuvor kompromittierten Paket abhängig waren. Durch das Sammeln gültiger npm-Veröffentlichungstoken von CI/CD-Runner-Systemen und Entwickler-Workstations veröffentlichte der Wurm nachgelagerte Pakete mit der eingeschleusten schädlichen Nutzlast erneut und erzeugte so eine kaskadierende Kette von Kompromittierungen. Dieser Mechanismus ermöglichte es dem Angriff, den ursprünglichen Keyv/Cacheable-Namespace zu verlassen und sich über Organisationsgrenzen hinweg auszubreiten.
Betroffene Pakete
Zu den wichtigsten kompromittierten Paketen gehörten:
|
Paketname |
Betroffene schädliche Version(en) |
Als sicher verifiziert / Wiederhergestellte saubere Version |
|
keyv |
6.0.0 (und nachfolgende bösartige Versionen) |
5.6.0 |
|
flat-cache |
6.1.24 |
6.1.23 |
|
Dateieintrag-Cache |
11.1.6 |
11.1.5 (oder vorherige stabile Version) |
|
cacheable-request |
13.0.20 |
13.0.19 (oder vorherige stabile Version) |
|
Cache-Manager |
7.2.10 |
7.2.9 |
|
cacheable |
2.5.1 |
2.5.0 (oder vorherige stabile Version) |
|
@cacheable/utils |
2.5.1 |
2.5.0 (oder vorherige stabile Version) |
|
@cacheable/memory |
2.2.1 |
2.2.0 (oder eine frühere stabile Version) |
|
@cacheable/node-cache |
3.1.2 |
3.1.1 (oder vorherige stabile Version) |
|
@cacheable/net |
2.1.1 |
2.1.0 (oder vorherige stabile Version) |
|
ecto |
5.0.1 |
5.0.0 (oder eine frühere stabile Version) |
Der Wurm breitete sich anschließend auf Pakete innerhalb von Organisationen wie Ornikar aus (darunter @ornikar/eslint-config-*, @ornikar/prettier-config, @ornikar/babel-preset-* und viele weitere), Qlik (@nebula.js/nucleus), HubSync (@hubsync/web-sdk-react) und zahlreiche andere. Eine vollständige, kontinuierlich aktualisierte Liste wird von Wiz Research in ihrem öffentlichen GitHub-Repository geführt.
Wichtig: Die npm-Registry hat sich während des Vorfalls rasch verändert. Am 4. August um 17:40 Uhr IST wurden für mindestens neun Kernpakete, darunter keyv@5.6.0, flat-cache@6.1.23 und cache-manager@7.2.9, frühere, fehlerfreie Versionen als aktuellste Versionen wiederhergestellt. Unternehmen müssen die Betroffenheit anhand der genauen Paketversionen überprüfen, die in den Lockfiles aufgeführt sind, und nicht anhand der aktuellen Registry-Tags.
Malware-Analyse
Übersicht über die Payload
Die Malware wird in einer zweistufigen Architektur bereitgestellt:
Stufe 1 – setup.mjs (Dropper): Dieses schlanke Node.js-Skript dient als anfängliche Payload. Es prüft, ob die Bun-JavaScript-Laufzeitumgebung vorhanden ist, und lädt, falls nicht, Bun v1.3.13 aus den offiziellen GitHub-Releases herunter. Anschließend übergibt es die Ausführung an das Haupt-Infostealer-Bundle, bevor es das temporäre Laufzeitverzeichnis löscht, um die forensischen Spuren zu minimieren.
Stufe 2 – Math_Symbol.js / math_init.js (Infostealer): Ein stark verschleiertes, 727.680 Byte großes kompiliertes Bundle, das über die Bun-Laufzeitumgebung ausgeführt wird. Dies ist die zentrale Engine zum Ausspähen von Anmeldedaten. Beide Dateinamen (Math_Symbol.js und math_init.js) wurden in freier Wildbahn beobachtet und enthalten identische Funktionalität mit demselben SHA-1-Hash.
Ziele des Anmelde- und Passwortdiebstahls
Der Infostealer listet systematisch folgende Daten auf und exfiltriert sie:
Persistenzmechanismen
Das Keyv-Repository enthielt separate Hooks für Claude Code (.claude/settings.json) und Visual Studio Code (.vscode/). Diese Persistenzmechanismen auf IDE-Ebene können die Payload ausführen, sobald ein Benutzer dem Arbeitsbereich vertraut oder die Projektkonfiguration zulässt, und bieten so einen sekundären Ausführungspfad, der unabhängig von den Lebenszyklus-Skripten von „npm install“ ist.
Die Malware installiert zudem einen Watcher zur Überwachung des Widerrufs von Anmeldedaten – eine Falle, die bei der Rotation von Tokens einen vom Angreifer bereitgestellten lokalen Handler auslöst. Betroffene müssen diesen Watcher entfernen, bevor sie Anmeldedaten rotieren.
Befehls- und Kontrollsystem
Die Malware ruft ihre C2-Domains über einen „eth_call“ aus einem Ethereum-Smart-Contract (StringListStore) ab, anstatt sie in die Nutzlast einzubetten. Diese Blockchain-basierte C2-Auflösung ermöglicht es dem Betreiber, die Infrastruktur zu aktualisieren, ohne die Malware ändern zu müssen. Die On-Chain-Historie zeigt, dass der Vertrag ursprünglich mit drei Domänen konfiguriert war, bevor er so aktualisiert wurde, dass er nur noch npm-cache[.]com zurückgibt. Der Vertragsinhaber wurde von einer Adresse finanziert, die zuvor wegen Betrugsaktivitäten markiert worden war.
Exfiltration
Gestohlene Daten werden mit einem hybriden AES-256- und RSA-4096-Verfahren verschlüsselt und anschließend über zwei Kanäle exfiltriert:
Die ersten Commits in den Exfiltrations-Repositories enthalten die Drohung: „IfYouBlockThisAPIKeyItWillCrashTheLiveProductionServersOfAllThirdPartyClients.“
Bekannte Indikatoren für eine Kompromittierung (IoCs)
|
Kategorie |
Indikator |
Beschreibung |
|
Domäne |
npm-cache[.]com |
Primäre C2- und Datenexfiltrationsdomain; bereitgestellt über Cloudflare |
|
Domäne |
registry[.]npmjs[.]org |
Endpunkt zur Token-Validierung, der zur Überprüfung der Anmeldedaten vor der Datenexfiltration missbraucht wird |
|
Domäne |
eth-mainnet[.]nodereal[.]io |
Ethereum-RPC-Endpunkt, der zum Abrufen von C2-Domains auf Basis von Smart Contracts verwendet wird |
|
Domäne |
go[.]getblock[.]io |
Ethereum-RPC-Endpunkt, der für die Abfrage von C2-Domains auf Basis von Smart Contracts verwendet wird |
|
Domain |
eth[.]llamarpc[.]com |
Ethereum-RPC-Endpunkt, der zur Ermittlung von C2-Domains auf Basis von Smart Contracts verwendet wird |
|
Domäne |
pypi-get[.]com |
Zusätzliche, vom Angreifer kontrollierte Infrastruktur |
|
Domäne |
js-mirror[.]com |
Weitere vom Angreifer kontrollierte Infrastruktur |
|
IPv4 |
104[.]21[.]35[.]216 |
Mit npm-cache[.]com verknüpfte Cloudflare-IP |
|
IPv4 |
172[.]67[.]167[.]200 |
Mit eth[.]llamarpc[.]com verknüpfte Cloudflare-IP-Adresse |
|
IPv4 |
185[.]44[.]207[.]215 |
IP, die mit go[.]getblock[.]io ETH RPC verknüpft ist |
|
IPv4 |
35[.]175[.]164[.]77 |
AWS-IP-Adresse, die mit eth-mainnet[.]nodereal[.]io verknüpft ist |
|
Dateiname |
Math_Symbol.js |
Verschleierte Infostealer-Nutzlast (727.680 Byte); über Preinstall-Skripte des npm-Pakets bereitgestellt |
|
Dateiname |
math_init.js |
Variante der Infostealer-Nutzlast mit identischer Funktionalität |
|
Dateiname |
setup.mjs |
Stage-1-Dropper; lädt die Bun-Laufzeitumgebung herunter und löst die Ausführung des Infostealers aus |
|
Datei-Hash (SHA-1) |
35a672cf34b996b91f3e1c28cbf3a05a37e036e4 |
Math_Symbol.js / math_init.js – Infostealer-Nutzlast |
|
Datei-Hash (SHA-1) |
686aa40d0fc22c8d569494543a0f891f359f2f99 |
setup.mjs im Verzeichnis .claude (Claude-Code-Hook) |
|
Datei-Hash (SHA-1) |
f525d52ceb966516686b482d3dc0137028cc6a63 |
„setup.mjs“ im Verzeichnis „.vscode“ (VS Code-Hook) |
|
User-Agent |
Bun/1.3.13 |
HTTP-User-Agent-Zeichenkette, die während des Bun-Laufzeit-Downloads und der C2-Kommunikation verwendet wird |
|
Dateisystempfad |
/tmp/bun-dl-*/ |
Temporäres Verzeichnis, das für den Download der Bun-Laufzeitumgebung und die Zwischenablage verwendet wird |
|
Dateisystempfad |
node_modules/keyv/Math_Symbol.js |
Speicherort der Infostealer-Nutzlast innerhalb des installierten Paketbaums |
|
Zeichenkette |
Shai-Hulud: Here We Go Again |
Beschreibung des GitHub-Repositorys, das für Exfiltrations-Repos verwendet wird |
|
Zeichenkette |
Wenn Sie diesen API-Schlüssel blockieren, stürzen die Live-Produktionsserver aller Drittanbieter-Clients ab |
Einschüchterungstext in den ersten Exfiltrations-Commits |
Erkennung und Bedrohungssuche
Sicherheitsteams sollten die folgenden Erkennungsmaßnahmen umsetzen:
Abhilfemaßnahmen und Behebungen
Sofortmaßnahmen
Systemwiederherstellung
Überprüfung der Cloud-Umgebungen und des Quellcodes
Absicherung der Lieferkette
Wenn Sie Bedenken hinsichtlich einer der in diesem Bulletin beschriebenen Bedrohungen haben oder Hilfe bei der Ermittlung der Maßnahmen benötigen, mit denen Sie sich vor den für Ihr Unternehmen relevantesten Bedrohungen schützen können, wenden Sie sich bitte an Ihren Kundenbetreuer oder kontaktieren Sie uns, um zu erfahren, wie Sie Ihr Unternehmen schützen können.