Kai Ole Hartwig
11 Min. Lesezeit
Kritisch

Keyv/Cacheable-npm-Kompromittierung: Mini-Shai-Hulud-Wurm vergiftet Hunderte Pakete über preinstall-Hook und Claude-Code-/VS-Code-Autostart

Am 4. August 2026 wurde die Release-Pipeline von keyv (619 Mio. Downloads/Monat laut Snyk) und rund einem Dutzend verwandter npm-Pakete aus dem cacheable-Umfeld kompromittiert. Ein neu eingefügter preinstall-Hook lädt eine verschlüsselte Bun-Runtime-Payload (Math_Symbol.js, ca. 728 KB), die Cloud- (AWS/GCP/Azure), CI/CD-, npm- und GitHub-Credentials erntet. Der Wurm verbreitet sich selbständig weiter, indem er gestohlene Publish-Tokens nutzt und dank npms Trusted-Publishing-Attestierung sogar kryptographisch „echt“ signierte bösartige Releases erzeugt. Zusätzlich legt er Autostart-Hooks in .claude/settings.json und .vscode/tasks.json ab — Code läuft dann schon beim Öffnen eines geklonten Repos in Claude Code oder VS Code, ganz ohne npm install. Snyk führt den Vorfall als SNYK-JS-KEYV-18515941 (Critical); eine offizielle CVE-Nummer war zum Zeitpunkt dieses Artikels noch nicht vergeben.

TL;DR — 90 Sekunden

Betroffen?

Projekte mit einer direkten oder transitiven Abhängigkeit auf keyv@6.0.0, cacheable@2.5.1, cacheable-request@13.0.20, flat-cache@6.1.24, file-entry-cache@11.1.6, cache-manager@7.2.10 sowie mehrere @cacheable/*-Scoped-Pakete (u. a. net, node-cache, memory). flat-cache/file-entry-cache erreichen viele Teams indirekt über ESLint.

Risiko?

Kritisch. Ein preinstall-Hook führt beim bloßen npm install Code mit Entwickler-/CI-Rechten aus, lädt eine verschlüsselte Bun-Payload nach und erntet Cloud-, CI/CD- und Registry-Credentials. Zusätzlich pflanzt der Wurm Autostart-Hooks in .claude/settings.json und .vscode/tasks.json, die schon beim Öffnen eines geklonten Repos auslösen — auch ohne Installation.

Sofortmaßnahme?

Betroffene Pakete per overrides/resolutions auf letzte saubere Versionen fixieren, Lockfiles ohne Skriptausführung neu aufbauen (--ignore-scripts), auf die dokumentierten IOCs prüfen — bevor Tokens rotiert werden (der Wurm überwacht Token-Widerruf und triggert dabei zusätzliche Payloads).

Empfehlung?

Jedes Team mit Node.js-/npm-Build- oder CI-Pipeline sollte umgehend die eigene Dependency-Tree gegen die betroffenen Pakete prüfen — auch transitiv, auch wenn keine der Top-Level-Dependencies direkt betroffen aussieht.

Kritikalität?

critical — aktiver, sich selbst verbreitender Lieferketten-Wurm mit Credential-Diebstahl, IDE-Persistenz und Anti-Forensik-Mechanismus gegen Token-Rotation.

Was ist das Problem?

Laut übereinstimmender Analyse von Snyk, Socket.dev, Cloudsmith, Wiz und weiteren Anbietern wurde am 4. August 2026 die Release-Pipeline von keyv — gepflegt vom Maintainer jaredwray — kompromittiert. Laut Snyks Rekonstruktion wurden gegen 09:02–09:17 UTC bösartige Commits ins keyv-Repository eingespielt, die einen preinstall-Skript-Hook ("preinstall": "node setup.mjs") sowie die zugehörigen Payload-Dateien hinzufügten. Um 09:35 UTC wurde keyv@6.0.0 mit diesem Hook auf npm veröffentlicht — inklusive gültiger npm-Provenance-Attestierung, da der Build-Prozess selbst unverändert und legitim über GitHub Actions lief. Genau das ist der zentrale Punkt: npm-Provenance bezeugt, dass ein bestimmter Workflow ein Artefakt gebaut hat — nicht, dass der Quellcode, der in diesen Workflow eingespeist wurde, vertrauenswürdig ist. War das Maintainer-Konto, der Repo-Zugriff oder die CI-Credentials vor der Veröffentlichung kompromittiert, signiert die Provenance ein bösartiges Artefakt genauso bereitwillig wie ein sauberes.

Der preinstall-Hook lädt einen rund 29,9 KB großen Loader (setup.mjs), der Plattform und Architektur erkennt, eine eigenständige Bun-Runtime herunterlädt und damit eine rund 728 KB große, polymorph Base91-kodierte zweite Stufe (Math_Symbol.js) ausführt — außerhalb der üblichen Node-basierten Monitoring-Pfade. Zwischen 10:09 und 10:14 UTC folgten die cacheable-Familie, danach weitere Pakete wie ecto@5.0.1 (10:28 UTC). Der Wurm verbreitet sich eigenständig: Er durchsucht nach weiteren Paketen des/der kompromittierten Maintainer, injiziert denselben preinstall-Hook, berechnet Integrity-/Shasum-Felder neu, erhöht die Versionsnummer und veröffentlicht über npms Trusted Publishing erneut — wodurch auch die Folge-Releases gültige Attestierungen erhalten.

Ein zweiter, vom Installationsschritt unabhängiger Auslösepfad macht den Vorfall besonders bemerkenswert: Das kompromittierte Repository enthält zusätzlich .claude/settings.json mit einem SessionStart-Hook sowie .vscode/tasks.json mit einer runOn: "folderOpen"-Task, die jeweils ein eigenes setup.mjs aufrufen. Wird ein betroffenes Repository lediglich in Claude Code oder VS Code geöffnet — ohne npm install, ohne Build —, läuft der Loader trotzdem. Damit reicht bei diesem Vorfall bereits das bloße Klonen und Öffnen eines Repos als Infektionsweg, nicht nur die Installation als Abhängigkeit.

Wer ist betroffen?

PaketVergiftete VersionLetzte saubere Version
keyv6.0.05.6.0
cacheable2.5.12.5.0 (letzte Version vor dem Vorfall prüfen)
cacheable-request13.0.2013.0.19 (letzte Version vor dem Vorfall prüfen)
flat-cache6.1.246.1.23
file-entry-cache11.1.611.1.5
cache-manager7.2.107.2.9
@cacheable/net, @cacheable/node-cache, @cacheable/memory u. a. Scoped Packagesje nach Paket, siehe Snyk-Advisory SNYK-JS-KEYV-18515941letzte Version vor dem Vorfall

Besonders relevant für TYPO3-/PHP-Teams: flat-cache und file-entry-cache erreichen viele Projekte nicht als direkte Abhängigkeit, sondern transitiv über ESLint im Frontend-Build (z. B. bei TYPO3-Sitepackages mit npm-basiertem Asset-Build). Ein npm ls ohne --all übersieht solche transitiven Treffer. Die genaue, vollständige Paketliste entwickelt sich mit der Untersuchung weiter — maßgeblich ist die jeweils aktuelle Fassung der Snyk-Advisory SNYK-JS-KEYV-18515941 sowie der Socket.dev- und Wiz-Analysen.

Auswirkungen

Der Payload zielt laut Snyk und Socket.dev breit auf Zugangsdaten: GitHub- und npm-Tokens, Cloud-Credentials (AWS-Metadatenüber IMDSv1/v2, GCP-Service-Account-Keys, Azure-Client-Secrets), HashiCorp-Vault-Tokens, Kubernetes-Service-Account-Tokens, SSH-Schlüssel, TLS-Zertifikate, Datenbank-Connection-Strings sowie den Speicher von GitHub-Actions-Runnern (inkl. OIDC-Tokens und Repository-Secrets). Exfiltriert wird u. a. über neu angelegte, öffentliche GitHub-Repositories sowie DNS-Tunneling.

Besonders heikel ist ein dokumentierter Persistenzmechanismus („gh-token-monitor“), der gestohlene GitHub-Tokens überwacht: Wird ein Token widerrufen, führt der Mechanismus einen vom Angreifer hinterlegten Handler aus — die übliche Reihenfolge „eingrenzen, dann Tokens rotieren“ wird damit gegen die eigene Incident Response gewendet. Wer Tokens rotiert, bevor die Persistenz entfernt ist, löst potenziell einen zusätzlichen, aktiv ausgelösten Schadcode-Pfad aus.

Da der Wurm sich selbständig über gestohlene Publish-Tokens weiterverbreitet und dabei gültige npm-Provenance-Attestierungen erhält, versagt an dieser Stelle ein rein auf Signaturprüfung gestütztes Vertrauensmodell: „kryptographisch signiert“ bedeutet hier ausdrücklich nicht „vertrauenswürdiger Quellcode“. Betroffen sind nicht nur Produktionsumgebungen, sondern auch Entwickler-Laptops und CI-Runner — überall dort, wo eines der Pakete installiert oder ein betroffenes Repository geöffnet wurde.

Mitigation / Sofortmaßnahmen

Operativer Entscheidungsblock

Schritt 1 — betroffene Pakete auf saubere Versionen fixieren

 

{
  "overrides": {
    "keyv": "5.6.0",
    "cacheable": "2.5.0",
    "cacheable-request": "13.0.19",
    "flat-cache": "6.1.23",
    "file-entry-cache": "11.1.5",
    "cache-manager": "7.2.9"
  }
}
// package.json (npm "overrides"); bei Yarn "resolutions" verwenden

 

Schritt 2 — Lockfile ohne Skriptausführung neu aufbauen

 

npm install --package-lock-only --ignore-scripts
rm -rf node_modules
npm cache clean --force
npm ci --ignore-scripts

 

Schritt 3 — Persistenz entfernen, bevor Tokens rotiert werden

 

# nach dem gh-token-monitor-Persistenzmechanismus suchen:
ls -la ~/.local/bin/ ~/.config/gh-token-monitor/ \
       ~/.config/systemd/user/ 2>/dev/null
ls -la ~/Library/LaunchAgents/ 2>/dev/null   # macOS

# forensische Kopie anlegen, dann Persistenz entfernen
# (systemd-Unit stoppen/deaktivieren bzw. LaunchAgent entladen),
# erst danach mit Schritt 4 fortfahren

 

Schritt 4 — Credentials rotieren

 

# GitHub-Token: widerrufen und neu ausstellen
# npm-Token: widerrufen (npm token revoke) und neu ausstellen
# Cloud-Keys (AWS/GCP/Azure), Vault-Tokens, Kubernetes-Service-Account-Tokens,
# SSH-Keys und Datenbank-Connection-Strings ebenfalls rotieren,
# wenn eine betroffene Maschine/CI-Runner die Pakete installiert hatte

Detection / Prüfung

Dependency-Tree prüfen (auch transitiv)

 

npm ls keyv flat-cache file-entry-cache cacheable-request \
  cacheable cache-manager @cacheable/net @cacheable/node-cache \
  @cacheable/memory --all

 

Nach bekannten Payload-Dateien und IOCs suchen

 

find "$HOME" /tmp -name setup.mjs -o -name Math_Symbol.js \
  -o -name gh-token-monitor.sh -o -name gh-token-monitor.service \
  -o -name com.user.gh-token-monitor.plist 2>/dev/null

# Prozesskette prüfen: node setup.mjs, das eine heruntergeladene
# bun-Binärdatei startet; temporäre Verzeichnisse nach dem Muster
# "bun-dl-*" suchen
find /tmp -maxdepth 2 -iname "bun-dl-*" 2>/dev/null

 

Kompromittierte preinstall-Hooks im node_modules-Baum aufspüren

 

find node_modules -name package.json -print0 | xargs -0 node -e '
  const fs = require("node:fs");
  for (const file of process.argv.slice(1)) {
    try {
      const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
      if (pkg.scripts?.preinstall === "node setup.mjs") {
        console.log(`${pkg.name}@${pkg.version}`);
      }
    } catch {}
  }
'

 

IDE-/Editor-Autostart-Hooks prüfen

 

# in jedem geklonten Repository prüfen, ob diese Dateien vorhanden
# sind und verdächtige setup.mjs-Aufrufe enthalten:
git -C /pfad/zum/repo show HEAD:.claude/settings.json 2>/dev/null
git -C /pfad/zum/repo show HEAD:.vscode/tasks.json 2>/dev/null | grep -A3 folderOpen

 

CI/CD- und Cloud-Audit-Logs prüfen

Betreiberempfehlung

Mid-Market

Dependency-Tree aller aktiven Node.js-/npm-Projekte (inkl. Frontend-Build-Toolchains wie TYPO3-Sitepackages mit ESLint) heute gegen die betroffene Paketliste prüfen. Lockfiles ohne Skriptausführung neu aufbauen, Persistenzmechanismus prüfen, dann erst Tokens rotieren.

Enterprise / Multi-Repo

Zentralen Scan über alle Repositories und CI-Pipelines fahren (SCA-Tooling oder das oben stehende npm ls --all-Kommando je Projekt), inklusive Entwickler-Laptops, auf denen betroffene Repos geklont/geöffnet wurden — nicht nur CI. Da der Wurm sich über legitime, attestierte Releases verbreitet, reicht eine reine Signaturprüfung nicht aus; Versionspins/Overrides sind Pflicht, bis die betroffene Paketliste als abschließend gilt.

Teams mit AI-Coding-Tools (Claude Code, Cursor, VS Code)

Jedes in den letzten Tagen geklonte oder geöffnete Repository gezielt auf .claude/settings.json und .vscode/tasks.json mit folderOpen-/SessionStart-Hooks prüfen — dieser Infektionsweg greift unabhängig davon, ob npm install überhaupt ausgeführt wurde.

Entscheidungsblock

Heute handeln, wenn: eines der betroffenen Pakete im Tree gefunden wurde oder ein Repo in den letzten Tagen geöffnet/geklont wurde. Diese Woche, wenn: Node.js-/npm-Toolchains im Einsatz sind, aber noch kein Scan lief. Beobachten, wenn: reine PHP-/TYPO3-Backends ohne npm-basierten Frontend-Build — hier bleibt Wachsamkeit sinnvoll, da sich die Paketliste noch entwickelt.

Was ich konkret getan habe

Ich behandle npm-Lieferketten-Würmer als Pipeline-Disziplin-Frage, nicht als Frage nach einem einzelnen bösen Paket. Für meine eigenen und betreuten Projekte mit npm-basiertem Frontend-Build (u. a. TYPO3-Sitepackages) habe ich den Dependency-Tree gegen die oben stehende Paketliste geprüft, --ignore-scripts als Standard für CI-Installationen verifiziert und die Renovate-Konfiguration so nachgezogen, dass betroffene Versionen explizit blockiert werden, bis die Advisory-Lage sich beruhigt hat. Zusätzlich habe ich stichprobenartig geprüft, ob in geklonten Repositories .claude/settings.json- oder .vscode/tasks.json-Dateien mit ungewöhnlichen Autostart-Hooks aufgetaucht sind — mit negativem Befund, aber genau diese Prüfung gehört aus meiner Sicht ab sofort zur Standard-Routine beim Öffnen fremder Repositories, nicht nur beim Installieren.

Häufige Fragen zum Keyv/Cacheable-npm-Wurm

Wie kann ein signiertes npm-Paket bösartig sein?+

npms Trusted-Publishing-Attestierung bezeugt, dass ein bestimmter GitHub-Actions-Workflow das veröffentlichte Artefakt gebaut hat — nicht, dass der Quellcode, der in diesen Workflow eingespeist wurde, vertrauenswürdig ist. War das Maintainer-Konto oder der Repo-Zugriff vor der Veröffentlichung kompromittiert, signiert die Provenance ein bösartiges Artefakt genauso bereitwillig wie ein sauberes.

Reicht npm install --ignore-scripts als Schutz?+

Gegen den preinstall-Hook-Pfad ja — --ignore-scripts verhindert, dass der Loader beim Installieren läuft. Gegen den zweiten Infektionsweg über .claude/settings.json und .vscode/tasks.json hilft das nicht: Der löst bereits beim Öffnen des Repos in Claude Code oder VS Code aus, unabhängig von npm install.

Warum zuerst Persistenz entfernen und erst dann Tokens rotieren?+

Weil ein dokumentierter Persistenzmechanismus („gh-token-monitor“) gestohlene GitHub-Tokens überwacht und bei Widerruf einen vom Angreifer hinterlegten Handler ausführt. Wird zuerst rotiert, kann das genau diesen zusätzlichen Schadcode-Pfad auslösen — die übliche Incident-Response-Reihenfolge wird hier gezielt gegen Verteidiger gewendet.

Ist das dasselbe wie der binding.gyp-Wurm vom Juni 2026?+

Nein, aber es gehört zur selben Familie selbst-verbreitender npm-Lieferketten-Würmer („Shai-Hulud“-Linie), über die wir hier bereits mehrfach berichtet haben — etwa den TanStack-Vorfall CVE-2026-45321 oder Miasma. Betroffene Pakete, Payload und Auslösepfade unterscheiden sich jeweils; die grundlegende Taktik (Lifecycle-Hook, Credential-Ernte, automatische Weiterverbreitung) ähnelt sich.

Betrifft mich das auch, wenn ich nur PHP/TYPO3 ohne npm einsetze?+

Direkt nicht, wenn Ihr Projekt keine npm-Abhängigkeiten hat. Sehr viele TYPO3-Sitepackages bauen ihre Frontend-Assets aber über npm-basierte Toolchains (Webpack, Vite, ESLint) — und genau dort landen flat-cache/file-entry-cache häufig transitiv über ESLint. Ein npm ls --all im Sitepackage-Verzeichnis schafft Klarheit.

Gibt es schon eine CVE-Nummer?+

Zum Zeitpunkt dieses Artikels nicht. Snyk führt den Vorfall unter der eigenen Advisory-ID SNYK-JS-KEYV-18515941 (eingestuft als Critical, CWE-506 — Embedded Malicious Code). Eine offizielle CVE-Zuweisung kann noch folgen; bis dahin ist die Snyk-Advisory die maßgebliche laufend aktualisierte Referenz.

Fazit

Der Keyv/Cacheable-Vorfall reiht sich in eine inzwischen lange Serie selbst-verbreitender npm-Würmer aus der „Shai-Hulud“-Familie ein — neu und bemerkenswert sind zwei Aspekte: Erstens nutzt der Wurm npms Trusted-Publishing-Attestierung aus, um seine eigenen bösartigen Releases kryptographisch „echt“ signieren zu lassen, was zeigt, dass Provenance-Prüfung allein kompromittierte Quellcode-Pipelines nicht erkennt. Zweitens erweitert er den Infektionsweg über die klassische npm install-Grenze hinaus in IDE-Autostart-Hooks (Claude Code, VS Code) — bloßes Öffnen eines geklonten Repos genügt. Wer Node.js-/npm-Toolchains einsetzt, sollte den eigenen Dependency-Tree prüfen, Lockfiles ohne Skriptausführung neu aufbauen und künftig auch Repository-lokale Editor-Konfigurationsdateien als Teil der Angriffsfläche behandeln — nicht nur package.json.

Quellen

Ich prüfe, mitigiere und validiere Ihre npm-/CI-Lieferkette gegen Würmer wie den Keyv/Cacheable-Vorfall.

Dependency-Tree-Audit auf betroffene Pakete, Lockfile-Rebuild ohne Skriptausführung, Renovate-/CI-Härtung gegen kompromittierte Trusted-Publishing-Releases, Prüfung von Repository-lokalen Editor-Autostart-Hooks.

Plattform-Betrieb statt Beratung auf Papier: Ich prüfe, patche und härte Ihre Software-Lieferkette laufend.

Über den Autor

Foto von Kai Ole Hartwig.

Kai Ole Hartwig

Freiberuflicher DevSecOps-Berater · OnlyOle Consulting

Programmiert seit 2002 – autodidaktisch gelernt, 2012 mit KO-Web selbständig gemacht. Über 100 Projekte, Fokus auf Security, Performance, Automatisierung und Qualität. Heute freiberuflich: DevSecOps-Beratung, Schulungen und Softwareentwicklung.