Kritisch

Wenn das Siegel echt ist und der Inhalt nicht: CVE-2026-45321, Mini Shai-Hulud und die erste validiert-signierte kompromittierte npm-Lieferung

Zwei identisch versiegelte cremefarbene Pergament-Briefumschläge mit oxblutfarbenen Wachssiegeln auf glattem Beton; der rechte Umschlag ist trotz intakten Siegels seitlich aufgeschlitzt und gibt einen abweichenden Briefinhalt frei. Daneben eine messingfarbene Juwelierlupe und ein einzelner oxblutfarbener Baumwollfaden, der aus dem Bild führt, in kühlem Nordlicht.

Am Abend des 11. Mai 2026, zwischen 19:20 und 19:26 UTC, sind im npm-Registry 84 bösartige Versionen über 42 @tanstack/*-Pakete erschienen. In den Stunden danach hat die gleiche Kampagne 65 UiPath-Pakete, das Mistral-AI-SDK auf npm und PyPI, das OpenSearch-Paket und Guardrails AI auf PyPI erreicht. Stand 12. Mai: über 170 betroffene Pakete, 404 bösartige Versionen, kumulativ mehr als 518 Millionen Downloads. Forschungsname: Mini Shai-Hulud. Threat-Actor: TeamPCP.

Was hat sich strukturell geändert? Erstmals trägt eine kompromittierte npm-Lieferung eine gültige SLSA Build Level 3 Provenance. Das Sigstore-Zertifikat ist echt, die Build-Pipeline ist legitim, die OIDC-Identität gehört dem Maintainer. Kompromittiert wurde nicht die Signatur, sondern der Inhalt, den sie beglaubigt. Wer ist betroffen? Jedes Team, das zwischen 19:20 UTC und 19:46 UTC ein npm install oder pip install auf einem der betroffenen Pakete ausgeführt hat — lokale Secrets als kompromittiert behandeln, OIDC-Bindungen rotieren. Was sollten Sie heute lesen? Operative Sofortmaßnahmen, Detection-Pfade, plus die strukturelle Folge: eine zweite Verifikationsstufe (Manifest-Diff gegen Baseline) wird zur regulären Pipeline-Stage neben der reinen Provenance-Prüfung.

Zusammenfassung in 90 Sekunden

Am 11. Mai 2026, 19:20–19:26 UTC, hat TeamPCP über den gekaperten TanStack/router-GitHub-Actions-Workflow 84 bösartige Versionen über 42 @tanstack/*-npm-Pakete veröffentlicht. In den Folgestunden: 65 UiPath-Pakete, mistralai auf npm und PyPI, opensearch (npm), guardrails-ai auf PyPI. Insgesamt über 170 Pakete, 404 bösartige Versionen, kumulativ > 518 Mio. Downloads. CVSS 9.6, kritisch.

Strukturell neu: erstmals tragen die kompromittierten Pakete eine gültige SLSA Build Level 3 Provenance. Der Angriff hat keinen einzigen Token gestohlen — er hat die legitime pull_request_target-Konfiguration des TanStack/router-Workflows ausgenutzt, GitHub-Actions-Cache zwischen Fork und Base vergiftet und das OIDC-Token aus dem Runner-Prozessspeicher extrahiert. Mit dieser legitimen Identität hat der Wurm die bösartigen Versionen veröffentlicht. Sigstore hat korrekt signiert, weil aus Plattform-Sicht alles in Ordnung war.

Akute Exposure: jedes CI- und Entwickler-Setup, das in der bekannten 26-Minuten-Spanne (plus rund 60 Minuten CDN-/Mirror-Replikation) ein npm install oder pip install auf einem der betroffenen Pakete ausgeführt hat. Die Malware exfiltriert lokale Secrets (SSH-Keys, Cloud-Tokens, GitHub-PATs, npm-Tokens, .env-Dateien) und das aktive OIDC-Token des CI-Runners. PyPI hat mistralai==2.4.6 und guardrails-ai==0.10.1 in Quarantäne; npm hat die TanStack-Versionen entfernt.

Empfehlung in dieser Reihenfolge: Lockfile-Inventur über den Mandanten-Bestand, CI-Build-Log-Verifikation für den Exposure-Zeitraum, Token-Rotation (OIDC-aktive Identitäten zuerst), npm install --ignore-scripts in Standard-Pipelines etablieren, eine Manifest-Diff-Stage zwischen Lockfile-Resolution und Tarball-Extraktion einziehen. Eine cosign-Verifikation allein erkennt diesen Bruch nicht.

Was CVE-2026-45321 technisch ist — und warum die SLSA-Provenance-Frage zählt

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 wir konkret getan haben

Wir haben 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). Wir haben dennoch die Cloud-Identitäten beider Pipelines rotiert. Parallel haben wir eine Manifest-Diff-Stage in unsere 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 haben wir eine Falco-Regel auf unseren Build-Hosts scharfgeschaltet.

Wir sind 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 unsere 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.

Häufige Fragen zu Mini Shai-Hulud / CVE-2026-45321

Sind wir betroffen, wenn @tanstack/react-router nur als Transitive-Dependency im Lockfile steht?+

Möglicherweise. Prüfen Sie die im Lockfile aufgelöste Version gegen die StepSecurity-Bad-Versions-Liste. Wenn die Version in der Bad-Spanne liegt und Ihr CI-Build zwischen 11.05.2026 19:00 UTC und 21:00 UTC lief, behandeln Sie die Pipeline-Identitäten als kompromittiert und rotieren Sie OIDC-aktive Token zuerst.

Was ist die operative Konsequenz davon, dass die SLSA-Provenance auf CVE-2026-45321 gültig ist?+

Eine reine cosign-Verifikation oder in-toto-Attestierungs-Prüfung erkennt diesen Vorfall nicht. Sie braucht eine zweite Stufe: einen Manifest-Diff gegen eine Baseline-Version oder einen Behavioural-Diff im Install-Hook. Sigstore-Validierung allein reicht 2026 nicht mehr — nicht weil die Validierung schlecht wäre, sondern weil die kompromittierte Lieferung im Pwn-Request-Pfad eine korrekt signierte Provenance erhält.

Wie prüfen wir nachträglich, ob unser GitHub-Actions-OIDC-Token am 11.05. zwischen 19:00 und 21:00 UTC missbraucht wurde?+

Die OIDC-Token sind kurzlebig und nicht ohne Weiteres aus Logs rekonstruierbar. Prüfbar sind hingegen: alle npm publish-, aws sts assume-role-with-web-identity-, gcloud auth login- und Azure-Token-Exchange-Aufrufe in den Audit-Logs Ihrer Cloud-Identitäten zwischen 19:00 UTC und 25:00 UTC am 11.05. Unerwartete Identitäten oder neue trusted-publisher-Bindungen in diesem Fenster sind das Indiz.

Müssen Kubernetes-Container, die npm install in der Build-Stage ausführen, wegen CVE-2026-45321 neu gebaut werden?+

Wenn der Image-Build in der bekannten Exposure-Spanne (11.05.2026 19:00–21:00 UTC) lief: ja. Wenn er davor oder danach lief: nein, sofern Sie Ihre Lockfiles auf saubere Versionen aktualisiert haben. Wenn Sie kein Lockfile haben (was wir nicht empfehlen): Sie wissen es nicht; bauen Sie neu mit aktuellen, gepatchten Versionen.

Wie reagieren wir, wenn mistralai==2.4.6 oder guardrails-ai==0.10.1 in einer Produktiv-KI-Agenten-Pipeline aktiv ausgeführt wurden?+

Token-Rotation aller LLM-API-Keys (Mistral, OpenAI, Anthropic — alle aus der .env des betroffenen Prozesses lesbar), Re-Pin auf bestätigt saubere Vorgänger-Versionen, vollständiger Re-Deploy. Wenn der Agenten-Prozess persistente Storage-Credentials hat (Vector-DB, Object Storage, SQL): diese ebenfalls rotieren. Bei Workload-Identity-Federation: FederatedIdentityCredential-Rebind statt einfachem Secret-Tausch.

Reicht es, pull_request_target durch pull_request zu ersetzen, um den Pwn-Request-Pfad zu schließen?+

Strukturell ja, weil pull_request keine Secrets aus dem Base-Repository in den Fork-Kontext exponiert. Operativ kann das bedeuten, dass bestimmte Preview-Build-Pipelines neu gedacht werden müssen. Wenn pull_request_target weiter notwendig ist: strikte Trennung halten — pull_request_target nur für Schritte, die keinen Code aus dem PR ausführen, plus ein getrennter workflow_run-Trigger mit Approval-Stufe für die Code-Ausführungs-Teile.

Bevor der nächste Mini-Shai-Hulud-Schub kommt — sprechen wir über Ihre zweite Verifikationsstufe.

Wir prüfen, rotieren und validieren Ihre npm-/PyPI-Pipeline gegen Mini-Shai-Hulud-Kompromittierungen — inklusive OIDC-Token-Audit und Manifest-Diff-Stage

Lockfile-Inventur über Ihren Mandanten-Bestand, CI-Build-Log-Verifikation für das Exposure-Fenster vom 11.05., Token-Rotation entlang der OIDC-Bindungen (Trusted-Publisher, AWS/Azure/GCP-Federation, npm-Token, GitHub-PATs), Einbau einer Manifest-Diff-Stage zwischen Lockfile-Resolution und Tarball-Extraktion, PoC-Validierung der Falco- oder Tetragon-Detection auf Ihren Build-Hosts — in dieser Reihenfolge, mit dokumentiertem Stand pro Schritt.

Das ist die operative Routine aus DevSecOps as a Service und unserer Standard-Linie für Lieferketten-Härtung. Wenn Sie Node.js-, React-/Vue-/Solid- oder Python-KI-Agenten-Stacks im DACH-Mittelstand betreiben, im Plattformbetrieb für mehrere Mandanten arbeiten oder eine kuratierte Artefakt-Pipeline mit SLSA-Provenance-Gate fahren, deren strukturelle Bewertung Sie nach diesem Vorfall neu treffen müssen — sprechen wir vor dem nächsten produktiven CI-Lauf.

Termin direkt vereinbaren