
IOC-Checker für den TanStack/Mini Shai-Hulud npm-Lieferkettenangriff (CVE-2026-45321)
# Mini Shai-Hulud Supply Chain Attack — IOC Checker
```bash
curl -fsSL https://raw.githubusercontent.com/nkopylov/tanscript-exploit-check/main/check-tanstack-exploit.sh | bash
```
Oder klonen und lokal ausführen:
```bash
git clone https://github.com/nkopylov/tanscript-exploit-check.git
cd tanscript-exploit-check
./check-tanstack-exploit.sh [Projektverzeichnis ...]
```
---
## Was passiert ist
Dieser Checker deckt **zwei Wellen** der Mini-Shai-Hulud-Supply-Chain-Angriffskampagne von **TeamPCP** ab:
### Welle 1: TanStack CI/CD-Kompromittierung (11. Mai 2026)
Am **11. Mai 2026** (19:20–19:26 UTC) veröffentlichte ein Angreifer **84 bösartige Versionen über 42 `@tanstack/*` npm-Pakete** in einem 6-Minuten-Fenster. Der Angriff traf auch Pakete von Mistral AI, UiPath, OpenSearch und anderen – insgesamt über 170 Pakete über npm und PyPI.
**Es wurden keine Anmeldedaten von Maintainern gestohlen.** Der Angreifer nutzte die CI/CD-Vertrauenskette selbst aus, und zwar über einen 3-stufigen Angriff:
1. **`pull_request_target`-Exploit** – Ein Wegwerf-GitHub-Fork eröffnete einen PR, der Angreifercode im Sicherheitskontext des Basis-Repositorys ausführte
2. **GitHub Actions Cache-Poisoning** – Der Code des Forks vergiftete den gemeinsam genutzten pnpm-Cache, der später legitime Release-Workflows infizierte
3. **OIDC-Token-Extraktion aus dem Prozessspeicher** – Der bösartige Code extrahierte npm-Publish-Token direkt aus dem Speicher des GitHub Actions Runners und erzeugte Pakete mit **gültigen SLSA Build Level 3 Provenance-Attestierungen**
### Welle 2: „atool“ npm-Kontoübernahme (19. Mai 2026)
Am **19. Mai 2026** (01:39–02:06 UTC) veröffentlichte das kompromittierte npm-Konto `atool` ([email protected]) **637 bösartige Versionen über 314 Pakete** in zwei automatisierten Wellen. Zu den stark betroffenen Zielen gehören:
- `size-sensor` (4,2 Mio. Downloads/Monat)
- `echarts-for-react` (3,8 Mio. Downloads/Monat)
- `@antv/scale` (2,2 Mio. Downloads/Monat)
- `timeago.js` (1,15 Mio. Downloads/Monat)
- 310+ weitere `@antv/*`- und andere Pakete
Diese Welle verwendete eine **Bun-basierte Payload** (498 KB `index.js`), ausgelöst über `"preinstall": "bun run index.js"`, mit einer zweiten Stufe, die in **impostor-Commits** versteckt war, die über den Fork-Objekt-Sharing-Exploit in das GitHub-Repo `antvis/G2` gepusht wurden.
### Was der bösartige Code tut (beide Wellen)
Beide Wellen verwenden dieselbe „Mini Shai-Hulud“-Toolkit-Familie:
- **Credential-Harvesting**: 80+ Umgebungsvariablen, AWS-Volkette (env → config → IMDSv2 → ECS → Secrets Manager), GitHub-PATs, npm-Token, SSH-Schlüssel, K8s-Token, Vault-Token, Passwort-Manager (1Password, Bitwarden, pass, gopass)
- **Persistenz**: `gh-token-monitor` (Welle 1) und `kitty-monitor` (Welle 2) Daemons via LaunchAgent/systemd; Hooks in `.claude/settings.json` und `.vscode/tasks.json`
- **Exfiltration**: P2P-Netzwerke (Welle 1), GitHub Git Data API + HTTPS getarnt als OpenTelemetry-Traces (Welle 2)
- **CI/CD-Missbrauch**: Workflow-Injection, die `toJSON(secrets)` ausgibt, npm OIDC-Token-Austausch
- **Totmannschalter**: `rm -rf ~/` falls GitHub-Token widerrufen wird, während der Daemon aktiv ist
- **Dead-Drop C2** (Welle 2): Pollt GitHub Commit Search API nach dem Schlüsselwort `firedalazer`, RSA-PSS-signierte Befehle
## Was dieses Skript prüft
| # | Prüfung | Beschreibung |
|---|---------|--------------|
| 1 | Totmannschalter | Persistenz-Daemons: `gh-token-monitor` (Welle 1), `kitty-monitor` (Welle 2) |
| 2 | Bösartige Prozesse | Bekannte Angreifer-Prozessnamen (beide Wellen) |
| 3 | Payload-Dateien | Bekannte bösartige Dateien nach Name und SHA-256-Hash (4 Hashes) |
| 4 | Claude Code Hooks | Injizierte Hooks in `.claude/settings.json` + generische SessionStart-Heuristik |
| 5 | VS Code Tasks | Injizierte Tasks in `.vscode/tasks.json` + generische `runOn: folderOpen`-Heuristik |
| 6 | GitHub Actions | `toJSON(secrets)` in **jedem** Workflow + `pull_request_target`-Warnung |
| 7 | npm Lockfiles | Kompromittierte Paketversionen in Lockfiles |
| 8 | optionalDependencies | Bösartiges `@tanstack/setup` und `@antv/setup` + 4 Impostor-Commit-SHAs |
| 9 | Netzwerkverbindungen | Aktive Verbindungen zur C2-Infrastruktur (5 Domains/IPs) |
| 10 | DNS-Cache | Frühere Auflösung von Angreifer-Domains (4 Domains) |
| 11 | Git-Branches | Dune-thematisiertes Branch-Namensmuster des Angreifers |
| 12 | Lebenszyklus-Skripte | **Heuristik:** `bun run` in preinstall/postinstall (installierte Pakete) |
| 13 | Dead-Drop C2 | `firedalazer`-Schlüsselwort und „Shai-Hulud“-Marker in der Git-Historie |
| 14 | GitHub-Abhängigkeiten | **Heuristik:** `github:`-Abhängigkeiten, die auf Commit-SHA in optionalDeps festgepinnt sind |
## Betroffene Pakete
### Welle 1: TanStack (42 Pakete)
Nur `@tanstack/router*` und `@tanstack/start*` waren betroffen. **NICHT betroffen:** `@tanstack/query*`, `@tanstack/table*`, `@tanstack/form*`, `@tanstack/virtual*`, `@tanstack/store`.
| Paket | Bösartige Versionen | Erste sichere Version |
|-------|---------------------|------------------------|
| `@tanstack/react-router` | 1.169.5, 1.169.8 | 1.169.9 |
| `@tanstack/router-core` | 1.169.5, 1.169.8 | 1.169.9 |
| `@tanstack/vue-router` | 1.169.5, 1.169.8 | 1.169.9 |
| `@tanstack/solid-router` | 1.169.5, 1.169.8 | 1.169.9 |
| `@tanstack/react-start` | 1.167.68, 1.167.71 | 1.167.72 |
| `@tanstack/router-plugin` | 1.167.38, 1.167.41 | 1.167.42 |
Siehe die [vollständige Sicherheitswarnung](https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx) für alle 42 Pakete.
### Welle 2: atool-Konto (314 Pakete)
Alle vom npm-Benutzer `atool` ([email protected]) veröffentlichten Pakete erhielten am 19. Mai 2026 bösartige Versionen. Zu den stark betroffenen Paketen gehören:
| Paket | Monatliche Downloads |
|-------|----------------------|
| `size-sensor` | 4,2 Mio. |
| `echarts-for-react` | 3,8 Mio. |
| `@antv/scale` | 2,2 Mio. |
| `timeago.js` | 1,15 Mio. |
Plus 310+ Pakete hauptsächlich im `@antv/*`-Scope (`@antv/g2`, `@antv/g6`, `@antv/l7`, `@antv/s2`, `@antv/x6`, `@antv/f2`, usw.), `ai-figure`, `timeago-react`, `jest-canvas-mock`, `jest-date-mock` und andere.
Siehe den [SafeDep-Bericht](https://safedep.io/mini-shai-hulud-strikes-again-314-npm-packages-compromised/) für die vollständige Liste.
## Behebung (falls kompromittiert)
> **KRITISCH: Deaktivieren Sie den Totmannschalter, BEVOR Sie Token widerrufen.** Die Malware löscht `$HOME`, wenn Token widerrufen werden, während der Daemon aktiv ist.
1. Töten Sie die Persistenz-Daemons (`gh-token-monitor` UND `kitty-monitor`) und entfernen Sie LaunchAgent/systemd-Dienste
2. Entfernen Sie Persistenz-Dateien (`.claude/router_runtime.js`, `.vscode/setup.mjs`, `~/.local/share/kitty/cat.py`, `/var/tmp/.gh_update_state`, usw.)
3. Löschen Sie `node_modules` und Lockfiles, installieren Sie neu mit `--ignore-scripts`
4. Rotieren Sie **ALLE** Anmeldedaten (npm, GitHub, AWS, GCP, SSH-Schlüssel, Vault-Token, Passwort-Manager-Token, usw.)
5. Blockieren Sie Angreifer-Domains auf DNS/Firewall-Ebene (`api.masscan.cloud`, `filev2.getsession.org`, `git-tanstack.com`, `t.m-kosche.com`)
6. Prüfen Sie Cloud-Anbieterprotokolle auf den 11.–19. Mai 2026
## Offizielle Ankündigungen und Referenzen
### Welle 1: TanStack (11. Mai)
- **CVE-2026-45321** (CVSS 9,6 Kritisch) — [CVE-Eintrag](https://www.cve.org/CVERecord?id=CVE-2026-45321)
- **GHSA-g7cv-rxg3-hmpx** — [GitHub Advisory](https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx)
- **TanStack Postmortem** — [tanstack.com/blog/npm-supply-chain-compromise-postmortem](https://tanstack.com/blog/npm-supply-chain-compromise-postmortem)
- **TanStack Härtung Nachbereitung** — [tanstack.com/blog/incident-followup](https://tanstack.com/blog/incident-followup)
- **GitHub Tracking Issue** — [TanStack/router#7383](https://github.com/TanStack/router/issues/7383)
### Welle 2: atool-Kontoübernahme (19. Mai)
- **SafeDep-Analyse** — [safedep.io/mini-shai-hulud-strikes-again-314-npm-packages-compromised/](https://safedep.io/mini-shai-hulud-strikes-again-314-npm-packages-compromised/)
### Sicherheitsforscher-Berichte
- [Socket.dev](https://socket.dev/blog/tanstack-npm-packages-compromised-mini-shai-hulud-supply-chain-attack)
- [Snyk](https://snyk.io/blog/tanstack-npm-packages-compromised/)
- [StepSecurity](https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem) (ursprüngliche Entdecker)
- [Wiz](https://www.wiz.io/blog/mini-shai-hulud-strikes-again-tanstack-more-npm-packages-compromised)
- [Orca Security](https://orca.security/resources/blog/tanstack-npm-supply-chain-worm/)
- [SecurityWeek](https://www.securityweek.com/tanstack-mistral-ai-uipath-hit-in-fresh-supply-chain-attack/)
## Härtungs-Prompts für KI-Codierungsagenten
Kopieren Sie diese Prompts in Ihren KI-Codierungsagenten (Claude Code, Cursor, Cline/OpenClaw, Windsurf, Hermes usw.), um Ihr Projekt gegen Supply-Chain-Angriffe wie diesen zu härten.
### Prompt 1: npm-Veröffentlichungsverzögerung (Quarantäne neuer Versionen)
> Härten Sie die npm-Konfiguration dieses Projekts gegen Supply-Chain-Angriffe. Führen Sie Folgendes aus:
>
> 1. **Exakte Versionen festlegen**: Entfernen Sie alle `^`- und `~`-Präfixe von jeder Abhängigkeit in `package.json`, sodass `npm install` niemals stillschweigend eine neu veröffentlichte Version zieht.
>
> 2. **Postinstall-Skripte standardmäßig deaktivieren**: Fügen Sie `ignore-scripts=true` zur `.npmrc` hinzu. Fügen Sie dann ein explizites `"preinstall"`-Skript in `package.json` hinzu, das nur die bekannten sicheren Lebenszyklus-Skripte ausführt, die dieses Projekt tatsächlich benötigt (falls vorhanden).
>
> 3. **Lockfile-only-Installationen in CI erzwingen**: Stellen Sie sicher, dass CI `npm ci` (nicht `npm install`) verwendet. Falls eine CI-Konfigurationsdatei vorhanden ist, überprüfen Sie dies. Falls nicht, notieren Sie es als manuellen Schritt.
>
> 4. **Provenance-Verifizierung hinzufügen**: Fügen Sie `npm audit signatures` als Schritt in der CI-Pipeline und als Pre-Push-Git-Hook hinzu.
>
> 5. **Ein Update-Policy-Skript erstellen**: Erstellen Sie ein `scripts/safe-update.sh`, das:
> - Einen Paketnamen als Argument nimmt
> - Überprüft, wann die neueste Version veröffentlicht wurde (`npm view <pkg> time --json`)
> - Das Update ablehnt, wenn die Version weniger als 3 Tage alt ist
> - Wenn älter als 3 Tage, führt `npm install <pkg>@latest --save-exact` aus
> - Eine Zusammenfassung der Änderungen ausgibt
>
> Ändern Sie keinen Anwendungscode. Berühren Sie nur Konfigurationsdateien, `.npmrc`, `package.json`-Skripte und CI-Konfiguration.
### Prompt 2: KI-Agentenkonfiguration härten
> Überprüfen und härten Sie die KI-Codierungsagenten-Konfiguration dieses Projekts gegen Supply-Chain-Injektionsangriffe (wie die TanStack/Mini-Shai-Hulud-Kampagne, die bösartige Hooks in `.claude/settings.json` und `.vscode/tasks.json` injiziert hat). Führen Sie Folgendes aus:
>
> **Claude Code (`.claude/`)**:
> 1. Überprüfen Sie `.claude/settings.json` und `.claude/settings.local.json` auf `hooks`-Einträge, die Shell-Befehle ausführen. Markieren Sie alles, was `.js`, `.mjs` oder `.sh`-Dateien ausführt – insbesondere aus `.claude/`, `.vscode/` oder `node_modules/`.
> 2. Entfernen Sie alle Hooks, die Sie keinem legitimen, benutzerdefinierten Zweck zuordnen können.
> 3. Fügen Sie eine `.gitignore`-Regel hinzu, um zu verhindern, dass `.claude/settings.local.json` committet wird (es sollte lokal bleiben).
>
> **VS Code (`.vscode/`)**:
> 1. Überprüfen Sie `.vscode/tasks.json` und `.vscode/launch.json` auf Tasks, die unerwartete Skripte oder Binärdateien ausführen.
> 2. Entfernen Sie alle Task-Einträge, die auf Dateien wie `setup.mjs`, `router_runtime.js` oder andere Namen verweisen, die nicht zu diesem Projekt gehören.
> 3. Überprüfen Sie `.vscode/extensions.json` auf Erweiterungen, die Sie nicht erkennen.
>
> **Cursor (`.cursor/`)**:
> 1. Überprüfen Sie `.cursor/settings.json` und alle Regeln-Dateien auf injizierte Befehle oder Hooks.
> 2. Gleiche Überprüfungen wie bei VS Code oben – Cursor erbt `.vscode/`-Konfiguration.
>
> **Allgemein**:
> 1. Überprüfen Sie auf `preinstall`, `postinstall`, `prepare` oder `prestart`-Skripte in `package.json`, die Sie nicht geschrieben haben. Markieren Sie verdächtige.
> 2. Überprüfen Sie `.github/workflows/` auf Workflows, die `pull_request_target` verwenden – markieren Sie dies als Sicherheitsrisiko mit einem Kommentar, der erklärt warum.
> 3. Stellen Sie sicher, dass `.gitignore` Agenten-Sitzungsdateien ausschließt, die Anmeldedaten preisgeben könnten (`.claude/projects/`, `.cursor/logs/`, usw.).
>
> Melden Sie, was Sie gefunden und was Sie geändert haben. Ändern Sie keinen Anwendungscode.
### Prompt 3: GitHub Actions-Härtung
> Überprüfen und härten Sie die GitHub Actions-Konfiguration in diesem Repository gegen CI/CD-Supply-Chain-Angriffe. Führen Sie Folgendes aus:
>
> 1. **Entfernen oder umbauen Sie alle `pull_request_target`-Trigger** – diese führen Workflow-Code im Kontext des Basis-Repositorys mit Zugriff auf Geheimnisse aus, selbst wenn sie von einem Fork ausgelöst werden. Ersetzen Sie durch `pull_request` + einen separaten, genehmigungsgesteuerten Workflow falls nötig.
>
> 2. **Pinnen Sie alle Drittanbieter-Aktionen auf vollständige Commit-SHAs** (nicht Tags oder Branches). Ersetzen Sie zum Beispiel `actions/checkout@v4` durch `actions/checkout@<vollständiger-sha>`. Fügen Sie einen Kommentar mit dem Tag zur Lesbarkeit hinzu.
>
> 3. **Wenden Sie das Prinzip der geringsten Rechte** auf jeden Workflow an. Fügen Sie explizite `permissions:`-Blöcke hinzu. Die meisten Workflows benötigen nur `contents: read`. Publish-Workflows benötigen `id-token: write` – und sonst nichts.
>
> 4. **Cache-Bereich einschränken**: Wenn `actions/cache` verwendet wird, stellen Sie sicher, dass Cache-Keys branch-begrenzt sind, um Cross-Branch-Poisoning zu verhindern. Fügen Sie `restore-keys` vorsichtig hinzu – stellen Sie keine Caches von nicht vertrauenswürdigen Branches wieder her.
>
> 5. **Fügen Sie StepSecurity Harden-Runner** als ersten Schritt in jedem Job hinzu: `step-security/harden-runner@v2` mit `egress-policy: audit` (oder `block`, wenn Sie Ihre erlaubten Endpunkte kennen).
>
> 6. **Überprüfen Sie auf Geheimnisse in Workflow-Logs**: Stellen Sie sicher, dass kein Workflow-Schritt `${{ secrets.* }}` oder `${{ toJSON(secrets) }}` auf stdout ausgibt.
>
> Melden Sie alle Änderungen. Ändern Sie keinen Anwendungscode.
## Lizenz
MIT