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.
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.
Fork & Umbenennung
TanStack/router wird geforkt und zu zblgg/configuration umbenannt, um die Entdeckung zu erschweren.
Umgeht Fork-Listen-Erkennung
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
Actions-Cache vergiften
Anstatt direkt zu publizieren, wird ein manipulierter pnpm-Store in den gemeinsamen GitHub Actions Cache geschrieben.
Cache wird branch-übergreifend geteilt
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
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
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.
# npm 11.10+; npm verwendet TAGE
min-release-age=7# pnpm 10.16+; pnpm verwendet MINUTEN (10080 = 7 Tage)
minimumReleaseAge: 10080
minimumReleaseAgeExclude:
- "@your-org/*"# Yarn 4.10+; Yarn verwendet MINUTEN
npmMinimalAgeGate: 10080
npmPreapprovedPackages:
- "@your-org/*"# Bun 1.3+; Bun verwendet SEKUNDEN (604800 = 7 Tage)
[install]
minimumReleaseAge = 604800
minimumReleaseAgeExcludes = ["@your-org/*"]version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule: { interval: daily }
cooldown:
default-days: 72. 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 einfachepull_request-Event für alles, das externe Beiträge berührt. - Setzen Sie
permissions: id-token: noneauf Workflow-Ebene. Gewähren Sieid-token: writenur 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.org83.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.
- Isolieren Sie zuerst den Host oder Runner. Widerrufen Sie noch keine Tokens.
- Erstellen Sie ein Image des Systems für die Forensik.
- Prüfen Sie
.claude/und.vscode/-Verzeichnisse auf persistierte Payload-Dateien wierouter_runtime.jsodersetup.mjs, dienpm uninstallüberleben. - Prüfen Sie auf
gh-token-monitor-Persistenz in~/Library/LaunchAgents/(macOS) oder~/.config/systemd/user/(Linux). - 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.
- 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] - 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]TanStack Postmortem — tanstack.com
- [2]GitHub Security Advisory GHSA-g7cv-rxg3-hmpx — github.com
- [3]Wiz Research, "Mini Shai-Hulud Strikes Again" — www.wiz.io
- [4]Socket, "TanStack npm Packages Compromised" — socket.dev
- [5]Snyk, "TanStack npm Packages Hit by Mini Shai-Hulud" — snyk.io
- [6]Endor Labs, "Shai-Hulud Compromises the @tanstack Ecosystem" — www.endorlabs.com
- [7]The Hacker News, "Mini Shai-Hulud Worm Compromises TanStack" — thehackernews.com
- [8]Orca Security, "Supply Chain Worm Attack Analysis" — orca.security
- [9]VentureBeat, "Shai-Hulud Worm 172 npm/PyPI Packages" — venturebeat.com
- [10]Phoenix Security, "TeamPCP Campaign Analysis" — phoenix.security
- [11]Aikido, "Mini Shai-Hulud is Back" — www.aikido.dev
- [12]Infosecurity Magazine, Erstmeldung — www.infosecurity-magazine.com
- [13]NHS England Digital Cyber Alert CC-4781 — digital.nhs.uk
- [14]pnpm Supply Chain Security Dokumentation — pnpm.io
- [15]Socket, "npm Introduces minimumReleaseAge" — socket.dev
