Am 28. August 2026 wurde @7nohe/openapi-react-query-codegen in einem neuen npm-Supply-Chain-Angriff kompromittiert. Das Paket generiert TypeScript-Clients und Hooks für TanStack Query aus OpenAPI-Schemas.[1][2][3]
Der Angreifer brauchte weder das npm-Passwort eines Maintainers noch einen gestohlenen langlebigen Publish-Token.
Die Schwachstelle lag im Release-Workflow.
Das Repository reagierte auf:
issue_comment
und ein Kommentar unter einem Pull Request mit exakt:
npm publish
konnte den Release-Pfad auslösen, ohne zuverlässig zu prüfen, ob der Kommentator Maintainer, Collaborator oder externer GitHub-Nutzer war.[1][2]
Danach:
PR-Code checkout
→ pnpm install
→ id-token: write
→ npm Trusted Publishing
So wurden 10 bösartige Versionen mit gültiger npm Provenance veröffentlicht.[1][3]
Die zentrale Lehre lautet:
Provenance kann korrekt belegen, woher ein Build stammt, obwohl der Build selbst bösartig ist.
Wichtig ist außerdem die Abgrenzung: @tanstack/react-query selbst wurde bei diesem Vorfall nicht kompromittiert. Betroffen war ein unabhängiger Codegenerator, der Code für TanStack Query erzeugt.[6][7]
Informationsstand: 31. August 2026.
TL;DR
| Frage | Verifizierte Antwort |
|---|---|
| Betroffenes Paket | @7nohe/openapi-react-query-codegen |
| Datum | 28. August 2026 |
| Bösartige Versionen | 10 |
| Davon stabile Versionen | 8 |
| Prereleases | 2 |
@tanstack/react-query kompromittiert? | Nein |
| Hauptvektor | Fehlkonfigurierter GitHub Actions issue_comment-Release-Workflow |
| Maintainer-Passwort nötig? | Nein |
| Long-lived npm Token nötig? | Nein |
| Publish-Berechtigung | id-token: write + npm Trusted Publishing |
| Gültige Provenance? | Ja |
| Provenance = sicher? | Nein |
| Execution Paths | binding.gyp, teilweise zusätzlich preinstall |
| Payload-Datei | 3FWCvzduYZg.js |
Aktuelles latest | 3.0.2 |
| Severity | Critical, CVSS 9.6 |
| CVE | Im Advisory am 31. August kein bekanntes CVE |
| Kampagnenfamilie | Mini-Shai-Hulud-bezogene/abgeleitete Aktivität |
| Sichere Sofortmaßnahme | Host isolieren und erreichbare Credentials von sauberem System rotieren |
Was geschah am 28. August?
GHSA-9pvf-vcx3-x239 listet 10 bösartige Versionen, veröffentlicht ungefähr zwischen 20:00 und 20:21 UTC.[1]
Stabile Versionen:
0.5.4
0.5.5
1.6.3
1.6.4
2.2.1
2.2.2
3.0.3
3.0.4
Prereleases:
0.0.0-365d4eb738d3146583431948d3ba6e27a32556be
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab
Der latest-Tag zeigte ab etwa 20:19:29 UTC auf 3.0.4 und wurde gegen 22:51 UTC auf das saubere 3.0.2 zurückgesetzt.[1]
TanStack Query selbst war nicht betroffen
Die Kurzform „TanStack Query gehackt“ ist falsch.
@7nohe/openapi-react-query-codegen ist ein unabhängiges Projekt, das Code für:
@tanstack/react-query
erzeugt.[6]
Das ist eine technische Abhängigkeit, keine Zugehörigkeit zum TanStack-Paket.
Auch TanStacks Postmortem zum Mai-Vorfall nennt Query explizit als nicht betroffen.[11]
Was macht das Paket?
Es generiert unter anderem:
- TypeScript API Clients,
- Query Keys,
queryOptions,infiniteQueryOptions,useQuery,useMutation,- Suspense- und Prefetch-Helfer.
Typischer Ablauf:
OpenAPI
↓
Codegen
↓
TypeScript Client
↓
TanStack Query Hooks
Wie verbreitet war es?
npm zeigte am 31. August ungefähr 155.000 wöchentliche Downloads.[6]
Diese Zahl ist dynamisch.
Entscheidender ist, dass ein Codegen-Tool auf Developer-Maschinen und CI-Runners läuft, also in Umgebungen mit GitHub-, SSH-, Cloud- und Deployment-Credentials.
Der Angriff begann in GitHub Actions
Der Workflow reagierte auf:
on:
issue_comment:
types: [created]
Gefährlich wurde die Kombination:
externer Kommentar
+ keine Autorisierungsprüfung
+ Checkout von PR-Code
+ Codeausführung
+ id-token: write
+ Publish
Ein Kommentar reichte als Release-Trigger
Der Workflow prüfte im Wesentlichen, ob der Kommentar zu einem PR gehörte und exakt npm publish enthielt.[1][2]
Ein Gate auf Rollen wie OWNER, MEMBER oder COLLABORATOR fehlte.
Damit konnte ein externer Account den privilegierten Pfad erreichen.
Checkout des Fork-Codes machte daraus Code Execution
Nach dem Checkout des PR-Codes lief:
pnpm install
Damit wurde untrusted content innerhalb eines privilegierten Release Jobs ausgeführt.
GitHub warnt seit langem davor, Code aus nicht vertrauenswürdigen Pull Requests in privilegierten Workflows auszuführen.[9]
id-token: write öffnete den Publish-Pfad
Der Job hatte:
permissions:
id-token: write
Das ist für OIDC-basiertes npm Trusted Publishing legitim.[10]
Das Problem war nicht OIDC selbst, sondern dass attacker-controlled Code in einem Job mit dieser Berechtigung ausgeführt wurde.
Kein Passwortdiebstahl war nötig
Laut StepSecurity brauchte der Angreifer weder npm-Passwort noch langlebigen Publish-Token.[2]
Altes Modell:
Token stehlen → publish
Neues Modell:
Trusted Workflow kontrollieren → legitime Identity erhalten → publish
Die Releases hatten gültige Provenance
Die Publikationen kamen über den echten Workflow und Trusted Publishing, deshalb trugen sie gültige Provenance-Attestierungen.[1][3]
Diese Provenance sagte korrekt:
dieser Artifact kam
über diesen Workflow
aus diesem Repository
Sie sagte nicht, dass der ausgeführte Code legitim war.
Provenance ist kein Malware-Scanner
Provenance beweist Herkunft und Build-Kontext.
Sie beweist nicht automatisch:
- sicheren Source Code,
- autorisierten PR,
- sichere Workflow-Logik,
- Malwarefreiheit.
Daher:
valid provenance ≠ safe package
Erster Execution Path: binding.gyp
Einige Versionen hatten keinen offensichtlichen preinstall.[1]
Stattdessen wurde binding.gyp eingebracht.
Der GYP/Python-Auswertungspfad wurde missbraucht, um os.system() zu erreichen und JavaScript auszuführen.[1][5]
Damit reicht eine Security-Regel, die nur preinstall oder postinstall sucht, nicht aus.
Zweiter Execution Path: preinstall
Spätere stabile Versionen enthielten zusätzlich:
"preinstall": "node 3FWCvzduYZg.js"
Das betraf:
0.5.5
1.6.4
2.2.2
3.0.4
Die vorherigen stabilen Versionen nutzten binding.gyp ohne expliziten Lifecycle Script.[1]
Die zwei Prereleases waren anders
Die 0.0.0-*-Prereleases enthielten einen bösartigen preinstall, aber wegen:
"files": ["dist"]
wurden die referenzierten Payload-Dateien nicht in den Tarball aufgenommen.[1]
Alle 10 Publikationen sind bösartig klassifiziert, aber nicht technisch identisch.
Hauptpayload 3FWCvzduYZg.js
Die stabilen bösartigen Tarballs enthielten:
3FWCvzduYZg.js
mit ungefähr 4,4 bis 6,4 MB.[1]
StepSecurity zeigte, dass 0.5.4 gegenüber 0.5.3 von etwa 41 KB auf mehr als 5,6 MB anwuchs.[2]
Solche Package-Size-Sprünge sind ein wichtiges Supply-Chain-Signal.
Runtime-Verhalten
In isolierten Runners beobachtete StepSecurity unter anderem:[2]
Node startet Payload
→ curl lädt Bun
→ Bun läuft aus /tmp/trinnyyyy-*
→ gh auth token
→ Git Credential Manager
→ Prüfung von ssh/scp
→ Prozessenumeration
→ temporäres updater.py
Dazu kamen GitHub-API-Zugriffe und Tests auf Google-Cloud-Metadata.
Welche Secrets gelten als gefährdet?
Wenn eine betroffene Version ausgeführt wurde, sollten alle für den Prozess erreichbaren Credentials als potenziell exponiert gelten:
GitHub
npm
SSH
Cloud
CI/CD
Deployment
Das bedeutet nicht, dass jedes Secret auf jedem Host tatsächlich exfiltriert wurde.
Warum Dev Dependencies gefährlich sind
„Nur Dev Dependency“ ist kein Sicherheitsargument.
Die Malware muss nur während:
npm install
pnpm install
yarn install
laufen.
Developer-Maschinen und CI-Systeme enthalten oft mehr wertvolle Secrets als der Browser-Build.
Package Installation ist eine Code-Execution-Oberfläche
Lifecycle Hooks wie:
preinstall
install
postinstall
prepare
können Code ausführen.
Auch Native-Addon-Pfade über node-gyp sind relevant.
Deshalb ist install nicht nur Download, sondern potenzielle Ausführung.
War es sicher TeamPCP?
Forscher von JFrog, Socket und anderen verbinden den Code mit Mini-Shai-Hulud-artiger Aktivität.[3][4]
Eine eindeutige Operator-Zuschreibung sollte aber nicht übertrieben werden.
Code-Reuse, bestehender Zugang oder Copycats sind möglich.[4]
Warum Mini Shai-Hulud weiter relevant ist
Die Kampagnenfamilie konzentriert sich auf Credential Theft, CI/CD, Package Registries und Propagation.[12]
Das wiederkehrende Muster:
Release-System kompromittieren
→ Publish-Rechte bekommen
→ vertrauenswürdig aussehendes Package veröffentlichen
→ auf Developer/CI Hosts laufen
→ neue Credentials suchen
Der TanStack-Vorfall im Mai war technisch anders
Am 11. Mai war das Router/Start-Repository betroffen.[11]
Die Kette kombinierte:
pull_request_target,- Cache Poisoning,
- OIDC-Token-Extraktion aus Runner Memory.
Ergebnis:
42 Pakete
84 bösartige Versionen
Query war auch im Mai sauber
TanStack erklärte nach dem Security Sweep ausdrücklich, dass Query nicht zu den kompromittierten Familien gehörte.[11]
Mai:
Router/Start betroffen
August:
unabhängiger Query-Codegenerator betroffen
Der Mai-Vorfall hatte reale Downstream-Auswirkungen
OpenAI berichtete, dass zwei Mitarbeitergeräte vom Mai-Angriff betroffen waren.[13]
OpenAI bestätigte credential-focused activity und begrenzte Exfiltration von Credential-Material, fand aber keine Hinweise auf kompromittierte User-Daten, Produktionssysteme oder IP.[13]
Das zeigt, dass selbst kurze Registry-Fenster schwere Folgen haben können.
August vs Mai
Mai
Fork PR
→ pull_request_target
→ Cache Poisoning
→ Trusted Release
→ OIDC Token aus Memory
→ Publish
August
Fork PR
→ öffentlicher "npm publish"-Kommentar
→ privilegierter Workflow
→ pnpm install
→ id-token: write
→ Trusted Publishing
Der August-Pfad war deutlich einfacher.
Wie prüft man die eigene Betroffenheit?
Durchsuche historische Lockfiles, SBOMs und CI-Logs nach allen 10 betroffenen Versionen.[1]
Prüfen:
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
SBOM
CI logs
dependency caches
Nur den aktuellen package.json anzusehen reicht nicht.
Wichtige IOCs
Öffentliche Indicators:[1][2][5]
3FWCvzduYZg.js
binding.gyp
is_it_this_simple.js
nu.js
/tmp/trinnyyyy-*/bun
/tmp/*/updater.py
Zusätzlich nach unerwarteten Bun-Downloads, gh auth token, Git Credential Manager Calls und node-gyp-Ausführung suchen.
Remediation
Wenn eine betroffene Version lief:[1][2]
1. Builds stoppen
2. Host isolieren
3. sauberes separates System nutzen
4. erreichbare Credentials rotieren
5. Sessions invalidieren
6. Audit Logs prüfen
7. Dependency Caches löschen
8. erzeugte Artifacts verwerfen
9. sauber neu bauen
Nicht nur npm-Credentials rotieren.
Welche Versionen sind sicher?
GitHub Advisory nennt 3.0.2 als known-good/patched und sagt, dass Versionen vor dem 28. August nicht betroffen sind.[1]
StepSecurity nennt als saubere Vorgänger:
0.5.3
1.6.2
2.2.0
3.0.2
npm zeigt am 31. August wieder latest = 3.0.2.[6]
Was wurde upstream geändert?
Laut Advisory:[1]
issue_comment-Trigger entfernt,- Releases auf Tag Push umgestellt,
- Trusted Publisher revoked,
- Long-lived Tokens rotiert,
latestauf3.0.2gesetzt,pre-Tag entfernt,- alle 10 Versionen deprecated,
- Removal bei npm angefordert.
Snyk klassifiziert die Kompromittierung ebenfalls als Critical mit CVSS 9.6 und unterstreicht damit die Schwere von Install-Time-Codeausführung.[8] Relevant sind außerdem TanStacks zusätzliche Hardening-Maßnahmen nach dem Mai-Vorfall für Cache, Workflows und Release-Pipeline.[14]
GitHub Actions härten
- Untrusted PR Code nie in privilegierten Jobs ausführen.
- Comment-driven Release nur mit Actor Authorization.
id-token: writenur im echten Publish Job.- Build und Publish trennen.
- Trusted Trigger oder manuelle Freigabe verwenden.
- Third-party Actions auf Commit SHA pinnen.[9]
Dependency Installation härten
Sinnvolle Kontrollen:
- Lockfiles,
- Frozen Installs,
- Minimum Release Age,
- Monitoring neuer Releases,
- Package-Size-Anomalien,
- Install-Script-Policy,
- sandboxed CI,
- Outbound Network Policy,
- Malware-Screening zusätzlich zu CVEs,
- SBOM,
- minimale Runner-Credentials.
Trusted Publishing bleibt sinnvoll.[10]
Aber:
Trusted Publishing
+
Trusted Workflow Design
gehören zusammen.
Produktions-Checkliste
Dependencies
- Lockfile verpflichtend.
- CI erkennt unerwartete Lockfile-Änderungen.
- Release Cooldown/Minimum Age.
- Neue Versionen nicht sofort in Produktion.
- Package-Size-Sprünge überwachen.
- Install Scripts prüfen.
- Unerwartetes
binding.gypmarkieren. - Malware-Erkennung zusätzlich zu CVE-Scanning.
GitHub Actions
- Fork Code läuft nie privilegiert.
-
issue_commenthat Authorization Gate. -
pull_request_targetnur bei echter Notwendigkeit. - Minimaler
GITHUB_TOKEN. -
id-token: writenur wo nötig. - Trusted Trigger für Publish.
- Build und Publish getrennt.
- Actions auf SHA gepinnt.
- Comment-driven Automation wird mit einem nicht autorisierten Nutzer negativ getestet.
- Release-Workflows checkouten keinen Code aus nicht vertrauenswürdigen Forks.
npm
- Trusted Publisher auf minimale Workflows begrenzt.
- Keine unnötigen Long-lived Publish Tokens.
- Realtime Publish Monitoring.
- Alerts für ungeplante Releases.
- Provenance verifizieren, aber nicht als Malware Verdict behandeln.
- Incident Runbook für Deprecation/Revocation.
Runners
- Ephemeral CI Runner.
- Minimale Secrets im Workspace.
- Short-lived Cloud Credentials.
- SSH Keys minimal scopen.
- Outbound Traffic überwachen.
- Dependency Install ohne Vollzugriff auf Infrastruktur.
- EDR/Runtime Monitoring.
- Schnelle Host-Isolation möglich.
Incident Response
- Owner definiert.
- Historische Lockfile-Suche möglich.
- CI Caches schnell löschbar.
- Sessions invalidierbar.
- Credential Exposure der Runner dokumentiert.
- Rotation von sauberem System.
- npm auf unautorisierte Publishes prüfen.
- GitHub Audit Logs auswerten.
POLPROG-Fazit
Der Angriff auf @7nohe/openapi-react-query-codegen zeigt sehr klar, wie Supply-Chain-Angriffe 2026 funktionieren.
Der Angreifer musste nicht npm selbst hacken, kein Maintainer-Passwort übernehmen und keinen klassischen Publish-Token stehlen.
Es reichte, untrusted code in einen Workflow mit legitimer Publish-Identity zu bringen.
Damit verschiebt sich die Sicherheitsgrenze zu:
CI/CD
Workflow Triggers
OIDC
Release Authorization
Dependency Execution
Die zweite Lehre ist Provenance.
Gültige Provenance war hier nicht falsch. Sie attestierte korrekt die Herkunft eines bösartigen Builds.
Die dritte Lehre ist Präzision.
TanStack Query selbst wurde nicht kompromittiert.
Betroffen war ein unabhängiges Tool im Query-Ökosystem.
Am 31. August sind die malicious versions bekannt, das Advisory veröffentlicht, latest wieder auf 3.0.2 und der Release Workflow geändert.[1][6]
Für Teams ist die wichtigste Frage nicht nur:
Haben wir dieses Paket genutzt?
Sondern:
Kann in unserem eigenen Release-System untrusted input einen Job mit Publish-Rechten erreichen?
Wenn die Antwort nicht sofort klar ist, sollte jetzt ein GitHub-Actions-Audit stattfinden.

