Die saubere Formulierung des Angriffs
TeamPCP hat keinen einzigen Token gestohlen. Es hat die legitime OIDC-Vertrauensbindung des TanStack/router-GitHub-Actions-Workflows entführt, eigene Pipeline-Logik in den Workflow injiziert und mit dieser Identität die bösartigen Versionen veröffentlicht. Aus npm-Sicht sah die Veröffentlichung exakt aus wie jede legitime TanStack-Release: gleiche OIDC-Identität, gleiche Trusted-Publisher-Bindung, gleicher Workflow-Pfad, gültige Sigstore-Provenance.
Die Angriffskette kombiniert drei bekannte Schwachstellenklassen, die alle drei einzeln dokumentiert sind. Erstens: pull_request_target ist ein GitHub-Actions-Trigger, der einem Workflow erlaubt, im Kontext des Base-Repositories mit dessen Secrets zu laufen, auch wenn die Workflow-Definition aus einem Fork stammt. Die GitHub-Dokumentation warnt seit 2020 explizit vor diesem Muster („Pwn Request“). Zweitens: GitHub-Actions-Cache wird im selben Schlüsselraum für Fork und Base geteilt. Ein Fork-PR kann einen Cache-Key vergiften, den ein anschließender Base-Workflow blind aus dem Cache lädt. Drittens: das OIDC-Token, das ein Runner für die npm-Trusted-Publisher-Authentifizierung erhält, lebt im Speicher des Runner-Prozesses. Wer Code mit denselben Privilegien im Adressraum bekommt, kann das Token aus dem Speicher abgreifen.
Die Verkettung ist die eigentliche Neuerung. Die einzelnen Bausteine sind alt, ihre Kombination zu einer reproduzierbaren Wurm-Kampagne mit OIDC-Identitäts-Hijacking und Provenance-Generierung ist es nicht.
Wer ist betroffen
Direkt betroffen sind drei Gruppen, in absteigender Schwere. Erstens: Teams, die zwischen 11.05.2026 19:20 UTC und 19:46 UTC ein npm install, npm ci oder pip install auf einem betroffenen Paket ausgeführt haben — in CI oder am Entwickler-Laptop. Zweitens: Teams, die in den letzten 30 Tagen mit npm audit oder Snyk-CLI eine Indirect-Dependency-Resolution auf einem dieser Pakete durchgeführt haben und Renovate-/Dependabot-Auto-Merge ohne 72-Stunden-Quarantäne fahren. Drittens: Teams, die SLSA-Provenance als alleiniges Eintritts-Gate in eine kuratierte Artefakt-Pipeline verwenden — ihre Pipeline hat die bösartigen Versionen als signiert durchgewunken.
Die betroffenen Paket-Namespaces sind @tanstack/* (42 Pakete, 84 Versionen), uipath-* und @uipath/* (65 Pakete), mistralai (npm und PyPI, mistralai==2.4.6 in Quarantäne), opensearch (npm, 1,3 Mio. wöchentliche Downloads) und guardrails-ai auf PyPI (guardrails-ai==0.10.1 in Quarantäne). Wer fertige Container-Images aus einer Registry konsumiert, deren Build-Pipeline keinen direkten npm-Pull macht, ist nicht direkt betroffen.
Mitigation und Sofortmaßnahmen
Die saubere Reihenfolge ist: erstens CI- und Entwickler-Logs auf npm install-Vorgänge zwischen 11.05.2026 19:00 UTC und 21:00 UTC durchsuchen (1h Sicherheitspuffer auf beiden Seiten der bekannten Exposure-Spanne); zweitens Lockfiles aller aktiven Projekte gegen die bekannte Bad-Versions-Liste matchen; drittens bei Treffer Token-Rotation in dieser Reihenfolge — OIDC-aktive Identitäten zuerst (GitHub-Actions-Trusted-Publisher, AWS/Azure/GCP-IAM-Credentials des Runners), dann npm-Tokens, dann SSH-Keys und .npmrc-Auth-Tokens, dann .env-Inhalte. Anschließend ~/.npm/_cacache, node_modules und package-lock.json löschen und mit aktuellen (gepatchten) Versionen neu installieren.
Für CI-Pipelines mit pull_request_target-Trigger: jeden Workflow prüfen, der diesen Trigger verwendet. Wenn der Workflow Secrets liest oder Schreibrechte hat, ist er ein potenzieller Pwn-Request-Vektor. Empfohlen: Workflow auf pull_request umstellen, falls operativ möglich; sonst harte Gates einbauen (Label-basiert, Branch-Schutz, explicit-allow-Liste der Contributor). Für Renovate-/Dependabot-Bots: offene PRs mit Lockfile-Updates auf betroffenen Paketen schließen und mit aktuellen Versionen neu erzeugen. Für PyPI: explizite Version-Pins auf die letzten vormistralai==2.4.6 und guardrails-ai==0.10.1 veröffentlichten sauberen Versionen setzen, bis der Maintainer eine bestätigt saubere Folge-Version veröffentlicht.
Detection und Prüfung
Lockfile-Inventur: eine vollständige Inventur über alle package-lock.json und yarn.lock im Mandanten-Bestand ist die Eintritts-Karte. CI-Build-Log-Verifikation: jeder CI-Run im Exposure-Zeitraum ist verdächtig; Build-Logs sind die Ground Truth, weil unter Cache-Poisoning der Build eine andere Version eingespielt haben kann als das Lockfile aussagt. Falco- oder Tetragon-Regel: ausgehende Verbindungen aus Prozessen, die direkt aus einem npm-, yarn- oder pnpm-Subprozess gestartet werden, sind ein hartes Detection-Signal für Install-Hook-Exfiltration. Provenance-Validierung gegen Manifest-Baseline: für Pipelines, die SLSA-Provenance bereits prüfen, ist der Befund struktureller — eine reine cosign-Verifikation hätte die Lieferung als legitim bestanden. Die strukturelle Antwort ist ein Manifest-Diff zwischen aktueller und Vorgänger-Version: unerwartete Erweiterungen von scripts.postinstall, neue bin-Definitionen, Veränderungen der Datei-Liste außerhalb des erwarteten Versions-Drifts werden zum Build-Stop.
Betreiberempfehlung
Sofort mitigieren, wenn Sie zwischen 11.05.2026 19:00 UTC und 21:00 UTC einen CI-Build oder lokales npm install / pip install auf einem der betroffenen Pakete ausgeführt haben — Token-Rotation komplett, Secrets als kompromittiert behandeln. 48h-Patch-Fenster akzeptabel, wenn Sie betroffene Pakete als Indirect-Dependency im Lockfile haben, aber keinen Install in der bekannten Exposure-Spanne nachweisen können — Lockfile auf aktuelle gepatchte Versionen anheben, Auto-Merge der Folge-Tage prüfen. Strukturmaßnahme im Wochenfenster, wenn Sie SLSA-Provenance als Eintritts-Gate in eine kuratierte Pipeline verwenden — Manifest-Diff-Stage als zweite Verifikationsstufe einbauen.
Mittelständische Teams haben in den meisten Fällen genau einen npm install-Schritt in der CI-Pipeline pro Mandant und kennen die direkten Top-Level-Dependencies. Die TanStack-Pakete kommen typisch über React-/Vue-/Solid-Frontend-Projekte, Mistral und Guardrails über KI-Agenten-Backends, OpenSearch über Such-/Logging-Pipelines. Zeitaufwand pro Mandanten-Repository: 20 bis 45 Minuten, plus Token-Rotations-Zeit von 1 bis 4 Stunden je nach Anzahl gebundener Cloud-Identitäten. Größere Organisationen mit zentralen npm-Mirrors (Artifactory, Verdaccio, Nexus) brauchen zusätzlich eine Mirror-Cache-Invalidierung und differenzierte Token-Rotation pro Mandant. Kubernetes-Cluster mit Image-Build-Pipelines im Zeitfenster sind direkt im Risiko-Pfad. Deklarative Build-Hosts (NixOS, Talos, Flatcar) schließen den Initial-Compromise-Pfad strukturell aus, sofern keine kompromittierte Version im Pin steht.
Was ich konkret getan habe
Ich habe am 11. Mai um 21:30 UTC eine Inventur über alle aktiven Mandanten-Lockfiles gefahren. Treffer in zwei Projekten: ein @tanstack/react-query-Pin in einem Frontend-Projekt (auf einer sauberen Version vor der Bad-Spanne) und ein mistralai-Pin in einer KI-Agenten-Pipeline (ebenfalls sauber). Ich habe dennoch die Cloud-Identitäten beider Pipelines rotiert. Parallel habe ich eine Manifest-Diff-Stage in meine Standard-Build-Pipeline eingezogen, die zwischen Lockfile-Resolution und Tarball-Extraktion jede Versionsdiff gegen die unmittelbar vorhergehende Version prüft. Falsch-Positiv-Rate in den ersten 24 Stunden Realbetrieb: etwa 1 pro 200 Builds — fast immer berechtigte Versions-Übergänge, die manuelle Bestätigung erfordern. Detection-seitig habe ich eine Falco-Regel auf meinen Build-Hosts scharfgeschaltet.
Ich bin nicht getroffen worden. Das ist keine Glanzleistung, sondern ein günstiges Zusammentreffen aus restriktiven Renovate-Regeln (Auto-Merge nur nach 72 Stunden Quarantäne) und der Tatsache, dass meine aktiven Frontend-Projekte auf Versionen lagen, die zum Angriffszeitpunkt nicht in der Bad-Spanne lagen.
Technischer Deep Dive: warum die SLSA-Provenance die Lieferung nicht rettet
SLSA — Supply-Chain Levels for Software Artifacts — formalisiert Vertrauen in Software-Lieferungen auf vier Stufen. Level 3 verlangt, dass der Build in einer gehärteten, isolierten Build-Plattform stattfindet und dass die Provenance kryptographisch signiert ist. Sigstore-Cosign generiert diese Signatur im npm-Ökosystem über die GitHub-Actions-Trusted-Publisher-Bindung: der Runner erhält ein OIDC-Token, das eine bestimmte Repository-Identität bestätigt, und Sigstore signiert die Provenance über diese Identität.
Der Bruch liegt in der Annahme, dass „signiert von der richtigen Identität“ implizit auch „durch die richtige Build-Logik produziert“ bedeutet. Diese Annahme war historisch tragfähig, weil der Runner-Prozess als isolierte Build-Umgebung galt. Mini Shai-Hulud zeigt, dass diese Isolation nicht hält, wenn der Workflow selbst Code aus einem nicht-vertrauenswürdigen Kontext (Fork-PR via pull_request_target, Cache-Eintrag mit Schlüssel-Kollision über Fork) im Runner-Adressraum ausführt. Sobald das passiert, ist die OIDC-Identität nicht mehr die der „richtigen Build-Logik“, sondern die des „Runners, den der Angreifer kurzzeitig kontrolliert“.
Das entscheidende Konstrukt ist die verbreitete Konfiguration actions/checkout@v4 mit ref: pull_request.head.sha in einem pull_request_target-Workflow. Sobald in dem Fork-PR-Code irgendwo ein postinstall-Script läuft (oder ein build-time Plugin, das Code im Runner-Adressraum ausführt), kann dieses Script den GITHUB_TOKEN, den Sigstore-OIDC-Token-Endpoint und sämtliche im Workflow gesetzten Secrets abgreifen. Mini Shai-Hulud nutzt diesen Pfad systematisch.
Fazit
Mini Shai-Hulud ist nicht der grösste npm-Vorfall des Jahres an reiner Paket-Zahl — Shai-Hulud im Sommer 2025 war breiter. Was den 11.05.2026 strukturell von den Vorgängern trennt, ist die gültige SLSA-Provenance auf der kompromittierten Lieferung. Das ist die Sorte Bruch, die eine DevSecOps-Architektur-Linie nicht in ihrer Schicht reparieren kann, sondern die eine zusätzliche Schicht erfordert. „Inhalt zusätzlich prüfen“ wird damit zur regulären operativen Stage neben „Signatur prüfen“, nicht zur Notmaßnahme.
Die Frage lautet nicht, ob SLSA als Spezifikation tragfähig ist — sie ist es, was sie spezifiziert, ist korrekt spezifiziert. Sie lautet, ob Ihre Pipeline die zweite Vertrauensstufe einbaut, die der Befund vom 11.05. notwendig macht, oder ob Sie weiterhin auf der ersten Stufe stehen und hoffen, dass der nächste Wurm nicht ebenfalls den Pwn-Request-Pfad nutzt. Die strukturelle Antwort ist die zweite Stufe, nicht der nächste Patch.
Persönlicher Hintergrund und technische Details zur Härtung von npm-Pipelines gegen kompromittierte Provenance: ole-hartwig.eu — Warum eine gültige Signatur 2026 nicht mehr reicht.