Mini Shai-Hulud npm Supply-Chain-Angriff Analyse
Sicherheit14. Mai 2026·11 Min. Lesezeit

Mini Shai-Hulud: Der npm-Angriff, der alle Best Practices umging

Drei kleine Fehlkonfigurationen führten zu 84 bösartigen Paketversionen. Die Angreifer veröffentlichten sie über die eigene Pipeline des Maintainers, signierten sie mit gültiger Provenienz. Kein Vertrauenssignal des JavaScript-Ökosystems schlug Alarm.

Inhaltsverzeichnis

TL;DR

Am 11. Mai 2026 veröffentlichten Angreifer 84 vergiftete Versionen von TanStack-npm-Paketen innerhalb eines Sechs-Minuten-Fensters. Sie stahlen keinen Token. Sie kaperten die eigene CI-Pipeline des Maintainers und ließen sie die Malware signieren. Die Pakete trugen gültige Sigstore-Provenienz. Das Ökosystem steht vor einem neuen Problem.

Die Zahlen

Falls Sie jemals ein TanStack-Paket installiert haben (Query, Router, Table, Form): Am 11. Mai 2026 besteht eine geringe Chance, dass Sie Malware ausgeführt haben. Das Zeitfenster war kurz und der Schaden begrenzt. Die dahinterstehende Technik verdient besondere Aufmerksamkeit.

84
Bösartige Versionen in 42 @tanstack/* Paketen
6 Min.
Veröffentlichungsfenster: 19:20 bis 19:26 UTC, 11. Mai 2026
12,7M
Wöchentliche Downloads von @tanstack/react-router allein
0
npm-Tokens, die während des gesamten Angriffs gestohlen wurden

Innerhalb von 48 Stunden weitete sich die Kampagne auf 172 Pakete und 403 bösartige Versionen über npm und PyPI aus, darunter Releases von Mistral AI, UiPath, OpenSearch und Guardrails AI.[1] Die kumulierte Download-Zahl betroffener Pakete: 518 Millionen.[4]

Die Kampagne heißt Mini Shai-Hulud. Die Zuschreibung erfolgt an eine Gruppe namens TeamPCP (auch bekannt als DeadCatx3, PCPcat, ShellForce und CipherForce). Dieselben Akteure stehen hinter dem Aqua-Trivy-Kompromiss im März 2026 und dem Bitwarden-CLI-npm-Kompromiss im April 2026.[5]

Was tatsächlich passiert ist

TanStack hatte die meisten Dinge getan, die die Security-Community von Maintainern seit Jahren fordert:

  • Zwei-Faktor-Authentifizierung auf jedem Maintainer-Konto
  • OIDC Trusted Publishing statt langlebiger npm-Tokens
  • Signierte Sigstore-Provenienz auf jedem Release

Keine dieser Maßnahmen half, weil die Angreifer nie versuchten, Zugangsdaten zu stehlen. Sie gingen eine Ebene tiefer und kompromittierten die Build-Pipeline selbst. Als die legitime Pipeline lief, veröffentlichte sie den Code des Angreifers unter TanStacks Identität, signierte ihn, attestierte ihn und markierte ihn als authentisch. Aus npm-Sicht war jedes bösartige Release ein echtes Release.

TanStack hatte die Haustür, die Hintertür und die Fenster abgeschlossen. Die Angreifer schoben eine gefälschte Blaupause in den Werkzeugkasten des Schlossers.

Die Angriffskette Schritt für Schritt

Die Angreifer verketteten drei bekannte Schwachstellenklassen in GitHub Actions. Keine davon ist einzeln neu; zusammen sind sie verheerend.

Angreifer-Seite
TanStack CI
1

Fork & Umbenennung

TanStack/router wird geforkt und zu zblgg/configuration umbenannt, um die Entdeckung zu erschweren.

Umgeht Fork-Listen-Erkennung

2

PR öffnen → pull_request_target auslösen

Der PR löst einen Workflow aus, der Fork-Code mit den Berechtigungen des Basis-Repos ausführt.

Klassische Pwn-Request-Fehlkonfiguration

3

Actions-Cache vergiften

Anstatt direkt zu publizieren, wird ein manipulierter pnpm-Store in den gemeinsamen GitHub Actions Cache geschrieben.

Cache wird branch-übergreifend geteilt

4

Maintainer merged einen PR

Der Release-Workflow stellt den vergifteten Cache wieder her. Angreifer-Code läuft nun mit Publish-Rechten.

OIDC-Token wird aus /proc/pid/mem extrahiert

OIDC-Token-Extraktion

Der vergiftete Code extrahiert den OIDC-Token aus dem Runner-Speicher und publiziert 84 Pakete auf npm, als wäre es TanStack selbst.

Gültige Sigstore-Provenienz auf jeder Version

Angriffskette · TanStack/router → npm Registry, 11. Mai 2026

Schritt 1 und 2: Der Pwn Request

Der Angreifer forkte das TanStack/router-Repository auf GitHub, benannte den Fork in zblgg/configuration um, um ihn schwerer auffindbar zu machen, und öffnete dann einen Pull Request zurück zu TanStack. Dieser PR löste einen Workflow aus, der GitHubs pull_request_target-Event nutzt.

Schritt 3: Cache-Vergiftung

Der geforkte PR versuchte nicht, direkt etwas zu veröffentlichen. Stattdessen schrieb er einen bösartigen pnpm-Store in den GitHub-Actions-Cache. GitHubs Actions-Cache wird über Branches desselben Repositories hinweg geteilt, einschließlich Caches, die von Fork-Pull-Requests geschrieben werden. Dieser gemeinsame Scope ist die Vertrauensgrenze, die es so nicht geben sollte.

Schritt 4: Das Warten

Die Angreifer warteten. Tage später mergte ein TanStack-Maintainer einen völlig unzusammenhängenden Pull Request in main. Der Release-Workflow lief, stellte den vergifteten Cache wieder her, und der Code des Angreifers wurde innerhalb von TanStacks vertrautem CI-Runner ausgeführt.

Die Payload: OIDC-Token-Extraktion

Das vergiftete Install-Skript las GitHubs OIDC-Token direkt aus dem Prozessspeicher des Runners (/proc/<pid>/mem). Mit diesem Token authentifizierte sich der Angreifer bei npm als das legitime TanStack/router-Repository über npms Trusted-Publisher-Bindung und veröffentlichte 84 bösartige Versionen über 42 Pakete in sechs Minuten.

Was die Malware mit Ihnen macht

Jedes vergiftete Paket enthielt eine neue Datei: router_init.js, ein 2,3 MB großes, obfuskiertes JavaScript-Bundle, das zur Installationszeit ausgeführt wird.[4] Es verhält sich unterschiedlich, je nachdem, wo es ausgeführt wird.

Auf CI-Runnern und Entwicklermaschinen

  • Stiehlt GitHub-Umgebungsvariablen, npm-Tokens, SSH-Private-Keys, AWS-/GCP-/Azure-Zugangsdaten und Kubernetes-Service-Account-Tokens
  • Exfiltriert über drei redundante Kanäle: die Typosquat-Domain git-tanstack[.]com, das Session-Messenger-Netzwerk und GitHub-API-"Dead Drops"[3]
  • Wurm-Verbreitung: nutzt gestohlene npm-Publish-Tokens, um vergiftete Versionen weiterer Pakete zu veröffentlichen, auf die das Opfer Schreibzugriff hat

Auf Entwickler-Workstations

Die Malware installiert einen persistenten Daemon namens gh-token-monitor über einen macOS-LaunchAgent oder eine Linux-systemd-Unit. Der Daemon fragt GitHub alle 60 Sekunden ab. Erhält er eine 40X-Antwort (der gestohlene Token wurde widerrufen), versucht er, rm -rf ~/ auszuführen.[3]

Deep Dive: Die Russisch-Sprachprüfung und die PyPI-Variante

Die Malware prüft die Systemsprache und beendet sich ohne Datenexfiltration, wenn sie auf Russisch eingestellt ist. Diese Signatur bestimmter osteuropäischer Bedrohungsakteure ist inzwischen bekannt und der einfachste Indikator für den ungefähren geografischen Ursprung.

Eine separate Variante zielte auf PyPI: mistralai@2.4.6 und guardrails-ai@0.10.1 wurden beide mit einem 13-zeiligen Trojaner veröffentlicht, der git-tanstack[.]com/tmp/transformers.pyz herunterlädt und ausführt. Die Python-Variante läuft nur auf Linux, enthält dieselbe Russisch-Locale-Prüfung und beendet sich, wenn weniger als vier CPUs vorhanden sind. Die CPU-Prüfung dient als einfache VM-/Sandbox-Umgehung.[3]

Warum dieser Angriff über TanStack hinaus wichtig ist

Laut Snyks Analyse ist dies der erste npm-Supply-Chain-Angriff, bei dem Pakete veröffentlicht wurden, die durch Provenienz-Attestierung kryptografisch nicht von legitimen zu unterscheiden sind.[5] Wiz und VentureBeat kommen in ihren technischen Analysen zum selben Ergebnis.[3][9]

Diese Schwelle macht die Kampagne architektonisch bedeutsam. Sie zeigt dem Ökosystem drei Fakten:

  • Sigstore-Badges und SLSA-Provenienz sind notwendig, aber allein unzureichend als Vertrauenssignale
  • OIDC Trusted Publishing schützt vor Zugangsdaten-Diebstahl, aber ein kompromittierter CI-Runner umgeht diesen Schutz
  • "Wir haben 2FA und keine langlebigen Tokens" ist keine vollständige Verteidigung mehr

Supply-Chain-Angriffe sind eine Ebene tiefer im Stack angekommen: vom Kompromittieren von Paket-Publishern zum Kompromittieren der Build-Infrastruktur von Paket-Publishern. Verteidiger brauchen verhaltensbasierte Sichtbarkeit während Installationen und Builds, zusätzlich zu Attestierungs-Checks an der Registry.

Was Sie jetzt tun sollten

Die effektivsten Verteidigungsmaßnahmen sind Konfiguration, keine neuen Tools oder Anbieter. Zusammen gestapelt hätten sie jede Welle dieser Kampagne blockiert.

1. Release-Cooldowns aktivieren

Bösartige npm-Pakete werden typischerweise innerhalb von Stunden erkannt und entfernt. Die TanStack-Versionen wurden innerhalb von 20 Minuten öffentlich erkannt.[1] Eine einfache zeitbasierte Verzögerung vor der Installation neu veröffentlichter Versionen eliminiert das Expositionsfenster nahezu vollständig.

.npmrc
# npm 11.10+; npm verwendet TAGE
min-release-age=7
pnpm-workspace.yaml
# pnpm 10.16+; pnpm verwendet MINUTEN (10080 = 7 Tage)
minimumReleaseAge: 10080
minimumReleaseAgeExclude:
  - "@your-org/*"
.yarnrc.yml
# Yarn 4.10+; Yarn verwendet MINUTEN
npmMinimalAgeGate: 10080
npmPreapprovedPackages:
  - "@your-org/*"
bunfig.toml
# Bun 1.3+; Bun verwendet SEKUNDEN (604800 = 7 Tage)
[install]
minimumReleaseAge = 604800
minimumReleaseAgeExcludes = ["@your-org/*"]
.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: npm
    directory: "/"
    schedule: { interval: daily }
    cooldown:
      default-days: 7

2. Lifecycle-Scripts in Dependencies deaktivieren

Die TanStack-Payload nutzte auch einen prepare-Lifecycle-Hook einer optionalDependency (das verwaist committete @tanstack/setup-Paket). pnpm v10+ deaktiviert postinstall-Scripts standardmäßig und erfordert explizites Allow-Listing über onlyBuiltDependencies in package.json. Für npm und Yarn verwenden Sie --ignore-scripts und aktivieren selektiv nur vertrauenswürdige Pakete.

3. Eigene CI/CD-Pipelines härten

Hier fand der eigentliche Angriff statt, und hier haben die meisten Teams die schwächsten Kontrollen.

  • Checken Sie niemals PR-Code in einem pull_request_target-Workflow aus. Verwenden Sie das einfache pull_request-Event für alles, das externe Beiträge berührt.
  • Setzen Sie permissions: id-token: none auf Workflow-Ebene. Gewähren Sie id-token: write nur dem spezifischen Job, der veröffentlicht.
  • Pinnen Sie Third-Party-GitHub-Actions per Commit-SHA, niemals per Tag.
  • Fügen Sie Repository-Owner-Guards zu Workflows hinzu, die mit erhöhten Berechtigungen laufen.
  • Behandeln Sie den GitHub-Actions-Cache als nicht vertrauenswürdig über die Fork-Base-Grenze hinweg.

4. Unkontrollierte Installationen reduzieren

npx, pnpm dlx und bunx führen bei jedem Aufruf Live-Auflösungen ohne Cache und ohne Cooldown durch. Jeder Aufruf ist eine Gelegenheit, eine kompromittierte Version zu laden. Pinnen Sie häufig verwendete Tools stattdessen als devDependencies.

5. Bekannte Indikatoren am Netzwerkrand blockieren

Blockieren Sie an DNS oder Ihrem Egress-Proxy:

  • git-tanstack[.]com
  • *.getsession.org
  • 83.142.209[.]194

6. Lockfile-Disziplin

Committen Sie package-lock.json oder pnpm-lock.yaml. In CI verwenden Sie immer npm ci oder pnpm install --frozen-lockfile. Keine Überraschungsauflösung zwischen lokaler Entwicklung und Produktion.

Falls Sie eine betroffene Version installiert haben

Jede Entwickler- oder CI-Umgebung, die am 11. Mai 2026 npm, pnpm oder yarn install gegen eine betroffene @tanstack/*-Version ausgeführt hat, sollte als kompromittiert betrachtet werden. Die Reihenfolge der Reaktion ist wichtig.

  1. Isolieren Sie zuerst den Host oder Runner. Widerrufen Sie noch keine Tokens.
  2. Erstellen Sie ein Image des Systems für die Forensik.
  3. Prüfen Sie .claude/ und .vscode/-Verzeichnisse auf persistierte Payload-Dateien wie router_runtime.js oder setup.mjs, die npm uninstall überleben.
  4. Prüfen Sie auf gh-token-monitor-Persistenz in ~/Library/LaunchAgents/ (macOS) oder ~/.config/systemd/user/ (Linux).
  5. Rotieren Sie in dieser Reihenfolge: npm-Tokens, GitHub-PATs und OIDC-Federations, Cloud-Zugangsdaten (AWS / GCP / Azure), SSH-Keys, CI/CD-Secrets, Kubernetes-Service-Account-Tokens.
  6. Pinnen Sie alle @tanstack/*-Dependencies auf Versionen, die vor 2026-05-11 19:00 UTC veröffentlicht wurden, oder auf die gepatchten Releases in GitHub Security Advisory GHSA-g7cv-rxg3-hmpx.[2]
  7. Installieren Sie von einem sauberen Lockfile neu.

Das große Ganze

Mini Shai-Hulud ist der architektonisch bedeutsamste npm-Supply-Chain-Angriff des Jahres 2026. Er demonstriert, dass ein Angreifer, der Code innerhalb eines GitHub-Actions-Runners eines Ziels ausführen kann, bösartige Pakete produzieren kann, die kryptografisch nicht von legitimen zu unterscheiden sind.

Die wirkungsvollsten Verteidigungsmaßnahmen (Release-Cooldowns, Lifecycle-Script-Einschränkungen, gehärtete CI-Workflows, disziplinierte Lockfile-Nutzung) existieren bereits in jedem großen Paketmanager. Die meisten Teams haben sie nur noch nicht aktiviert.

Aktivieren Sie sie diese Woche.

Sources

  1. [1]TanStack Postmortem tanstack.com
  2. [2]GitHub Security Advisory GHSA-g7cv-rxg3-hmpx github.com
  3. [3]Wiz Research, "Mini Shai-Hulud Strikes Again" www.wiz.io
  4. [4]Socket, "TanStack npm Packages Compromised" socket.dev
  5. [5]Snyk, "TanStack npm Packages Hit by Mini Shai-Hulud" snyk.io
  6. [6]Endor Labs, "Shai-Hulud Compromises the @tanstack Ecosystem" www.endorlabs.com
  7. [7]The Hacker News, "Mini Shai-Hulud Worm Compromises TanStack" thehackernews.com
  8. [8]Orca Security, "Supply Chain Worm Attack Analysis" orca.security
  9. [9]VentureBeat, "Shai-Hulud Worm 172 npm/PyPI Packages" venturebeat.com
  10. [10]Phoenix Security, "TeamPCP Campaign Analysis" phoenix.security
  11. [11]Aikido, "Mini Shai-Hulud is Back" www.aikido.dev
  12. [12]Infosecurity Magazine, Erstmeldung www.infosecurity-magazine.com
  13. [13]NHS England Digital Cyber Alert CC-4781 digital.nhs.uk
  14. [14]pnpm Supply Chain Security Dokumentation pnpm.io
  15. [15]Socket, "npm Introduces minimumReleaseAge" socket.dev

Bereit für Ihr nächstes Projekt?

Lassen Sie uns gemeinsam Ihre digitale Präsenz auf das nächste Level bringen.

Projekt starten