
Shell-Skript zum Erkennen von Indikatoren für den TanStack npm Supply-Chain-Angriff (CVE-2026-45321 / GHSA-g7cv-rxg3-hmpx)
Erkennen Sie Indikatoren des TanStack npm Supply-Chain-Angriffs auf einem Entwicklungsrechner, einem Repository oder einem CI-Runner. Bash-Skript, Docker-Image und GitHub Action – gleiche Engine, drei Einstiegspunkte.
CVE-2026-45321 / GHSA-g7cv-rxg3-hmpx
Am 11. Mai 2026 veröffentlichten Angreifer 84 schädliche Versionen über 42 @tanstack/* Pakete via GitHub Actions Cache-Vergiftung. Die Nutzlast stiehlt GitHub-Tokens, npm-Tokens, AWS-/GCP-/Azure-Anmeldeinformationen und installiert einen Dead-Man's-Switch-Daemon, der ~/ löscht, sobald der gestohlene Token widerrufen wird.
Wählen Sie den Einstiegspunkt, der zu Ihrer Situation passt.
TAG=v1.0.0
curl -fsSLO https://github.com/fabriziosalmi/tanstack-compromise-checker/releases/download/$TAG/check.sh
curl -fsSLO https://github.com/fabriziosalmi/tanstack-compromise-checker/releases/download/$TAG/check.sh.sha256
sha256sum -c check.sh.sha256
bash check.sh --online
docker run --rm -v "$PWD":/scan \
ghcr.io/fabriziosalmi/tanstack-compromise-checker:v1.0.0 \
/scan true fail tanstack-findings.json '' GHSA-g7cv-rxg3-hmpx
Das Image ist Multi-Arch (linux/amd64, linux/arm64) und wird mit einer via GitHub OIDC signierten Build-Provenienz ausgeliefert. Überprüfen Sie vor der Ausführung:
gh attestation verify \
oci://ghcr.io/fabriziosalmi/tanstack-compromise-checker:v1.0.0 \
--repo fabriziosalmi/tanstack-compromise-checker
permissions: {}
jobs:
check:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: fabriziosalmi/tanstack-compromise-checker@v1
with:
scan-dir: .
online: 'true'
fail-on: fail
Ein vollständig gehärteter Workflow befindet sich unter .github/workflows/tanstack-check.yml und ist derselbe Workflow, den dieses Repository gegen sich selbst ausführt.
| # | Check | Description |
|---|---|---|
| 1 | Dead-man's switch | ~/.local/bin/gh-token-monitor.sh, LaunchAgents + LaunchDaemons (macOS), systemd Benutzer- + System-Units (Linux), laufende Prozesse |
| 2 | Persistence | Shell-RC-Dateien, Benutzer-/System-Crontab, /etc/cron.*, XDG-Autostart, globales Git core.hooksPath |
| 3 | Credentials | sensible Umgebungsvariablen, ~/.npmrc, ~/.yarnrc.yml, ~/.aws/credentials, ~/.config/gh/hosts.yml, ~/.netrc, ~/.docker/config.json, ~/.kube/config, Auflistung von .env*-Dateien |
| 4 | Network IOC | laufende node-Prozesse mit etablierten ausgehenden TCP-Verbindungen (heuristisch, manuelle Überprüfung) |
| 5 | Repo scan | in package.json deklarierte Abhängigkeiten + in Lockdateien festgelegte Versionen (package-lock.json, yarn.lock, pnpm-lock.yaml) |
| 6 | Installed | node_modules/@tanstack/*/package.json wird mit der Liste bekannter schädlicher Versionen abgeglichen, dann mit der npm-Registry time[<version>] bei --online |
| 7 | Actions hints | .github/workflows/* wird gescannt auf pull_request_target, fehlendes --ignore-scripts, Nutzung von actions/cache |
| 8 | Mini Shai-Hulud IOCs | Payload-Dateien in node_modules (router_init.js, tanstack_runner.js), @tanstack/setup als optionalDependency, Manipulation von KI-Tool-Konfigurationen, C2-Domains im Quellcode, Angreifer-Commit-Autor + Branch-Muster, mit Lösegeld markierte npm-Tokens, sekundäre wurmverbreitete Pakete, plus Info-Level-Heuristiken für unbekannte Payload-Formen |
Mit --online ruft das Skript zur Laufzeit auch die GHSA-Advisory ab, sodass die Erkennungsabdeckung dem Live-Zustand der Advisory folgt, anstatt einer fest codierten Liste von Versionen.
Betroffene Familie: @tanstack/router, @tanstack/react-router, @tanstack/history, @tanstack/start, @tanstack/eslint-plugin-router und verwandte Pakete.
Saubere Familien (nicht betroffen): @tanstack/react-query, @tanstack/react-table, @tanstack/react-virtual, @tanstack/form, @tanstack/store.
# Quick check (current user's home)
bash check.sh
# Online mode: query the GHSA advisory and npm registry publish-time
bash check.sh --online
# Scan a specific directory
bash check.sh --scan-dir /path/to/your/repos
# JSON output for CI/SIEM integration
bash check.sh --json > findings.json
# Suggest pin commands for affected repos (dry-run)
bash check.sh --scan-dir /path/to/repos --fix
# Provide an extended known-bad list
bash check.sh --bad-versions-file ./extra-bad-versions.txt
| Flag | Description |
|---|---|
--scan-dir DIR | Root-Verzeichnis zum Scannen (Standard: $HOME). Weigert sich, Systemverzeichnisse wie /, /etc, /usr zu scannen. |
--online | Ruft die GHSA-Advisory und das time[<version>] der npm-Registry ab, um die Kompromittierung zu bestätigen. Standardmäßig deaktiviert – Opt-in. |
--ghsa GHSA-ID | Überschreibt die Advisory-ID, die bei --online verwendet wird (Standard GHSA-g7cv-rxg3-hmpx). |
--attack-window-start ISO, --attack-window-end ISO | Überschreibt das Veröffentlichungszeitfenster, das bei --online verwendet wird. |
--fix | Gibt empfohlene Pin-Befehle für betroffene Repos aus (standardmäßig Trockenlauf). |
--apply | Mit --fix: Opt-in zur Ausführung. Verweigert derzeit noch blindes update; manuelles Pinning ist erforderlich. |
--yes, -y | Überspringt die Bestätigungsaufforderung für --apply. |
--json | Gibt Ergebnisse als JSON auf stdout aus (impliziert --quiet). |
--bad-versions-file F | Fügt Einträge (pkg@version, eine pro Zeile) zur Liste bekannter schädlicher Versionen hinzu. |
--no-color | Deaktiviert ANSI-Farben. |
--quiet, -q | Unterdrückt die Ausgabe pro Prüfung, gibt nur Zusammenfassung aus. |
-h, --help | Zeigt Hilfe an. |
| Code | Meaning |
|---|---|
| 0 | Sauber – keine Indikatoren im gescannten Bereich |
| 1 | Nur Warnungen – Überprüfung empfohlen |
| 2 | Fehler – Kompromittierungsindikatoren vorhanden |
| 3 | Tool-/Anwendungsfehler |
Dieses Repository schützt sich gegen dieselbe Angriffsklasse, die es erkennt. Konkret:
uses: ist auf einen 40-Zeichen-Commit-SHA festgelegt, nicht auf ein schwebendes Tag.permissions: {} auf oberster Ebene; Jobs gewähren nur, was sie benötigen.actions/checkout wird mit persist-credentials: false aufgerufen, sodass kein authentifiziertes Git-Remote in $GITHUB_WORKSPACE verbleibt.step-security/harden-runner ist der erste Schritt jedes Workflows und überwacht den Runner-Ausgang.main; Ergebnisse werden als SARIF hochgeladen.gh attestation verifizieren.check.sh.sha256, die alle installierbaren Artefakte abdeckt.Die vollständige Richtlinie befindet sich in SECURITY.md.
Verwenden Sie nicht curl | bash für irgendein Sicherheitstool, einschließlich dieses. Laden Sie immer herunter, überprüfen Sie die Prüfsumme, inspizieren Sie und führen Sie dann aus.
━━ 1 / 8 DEAD-MAN'S SWITCH ARTEFACTS
✔ No dead-man's switch artefacts found
━━ 2 / 8 PERSISTENCE VECTORS
✔ No persistence vectors detected
━━ 3 / 8 TOKEN / CREDENTIAL EXPOSURE
✔ No credential exposure detected
━━ 4 / 8 NETWORK INDICATORS
✔ No node TCP connections currently established (or none observable)
━━ 5 / 8 REPO SCAN — package.json + lockfiles
ℹ Found 12 package.json + 8 lockfile(s)
✔ No compromised family declared in any package.json
✔ No compromised pins found in any lockfile
━━ 6 / 8 INSTALLED node_modules — direct version check
✔ No compromised packages in installed node_modules
━━ 7 / 8 GITHUB ACTIONS HARDENING HINTS
✔ No risky GitHub Actions patterns detected (in scanned scope)
━━ 8 / 8 MINI SHAI-HULUD PAYLOAD + AUXILIARY IOCs
✔ No Mini Shai-Hulud payload / auxiliary IOCs detected
━━ SUMMARY
Passed: 8 Warnings: 0 Failed: 0
Scope : /Users/alice/dev
✔ No indicators of compromise within scope: /Users/alice/dev
Note: a clean result for /Users/alice/dev does not certify the rest of the system.
Widerrufen Sie Ihren GitHub-Token NICHT, bevor Sie den Daemon stoppen – der Dead-Man's-Switch wird
rm -rf ~/ausführen, sobald der Token widerrufen wird.
launchctl bootout gui/$UID ~/Library/LaunchAgents/com.user.gh-token-monitor.plistlaunchctl unload ~/Library/LaunchAgents/com.user.gh-token-monitor.plistsystemctl --user stop gh-token-monitor && systemctl --user disable gh-token-monitorrm -f ~/.local/bin/gh-token-monitor.sh~/.aws/credentials, ~/.kube/config, ~/.config/gh/hosts.yml, ~/.npmrc.bash 4+jq (empfohlen) – package-lock.json Parsenpython3 (optionaler Fallback) – wird verwendet, wenn jq fehltcurl – erforderlich für --onlinelsof oder ss (optional) – Netzwerk-IOC-HeuristikDas Docker-Image bündelt alle oben genannten. Verwenden Sie es auf Systemen, auf denen Sie diese Tools nicht installieren können oder möchten.
Issues und Pull-Requests sind willkommen. Beachten Sie, dass dieses Repository CODEOWNERS verwendet: Alle PRs benötigen eine Überprüfung durch einen Betreuer.
MIT.