Dňa 28. augusta 2026 bol kompromitovaný npm balík @7nohe/openapi-react-query-codegen, nástroj generujúci TypeScript klientov a hooky pre TanStack Query z OpenAPI schém.[1][2][3]
Útočník nepotreboval npm heslo maintainera ani ukradnutý dlhodobý publish token.
Cesta viedla cez release workflow v GitHub Actions.
Repozitár reagoval na:
issue_comment
a komentár v pull requeste s presným textom:
npm publish
mohol spustiť release path bez dostatočného overenia, či komentujúci je maintainer, collaborator alebo úplne externý používateľ GitHubu.[1][2]
Workflow potom:
checkoutoval kód z PR
→ spustil pnpm install
→ mal id-token: write
→ publikoval cez npm Trusted Publishing
Výsledkom bolo 10 škodlivých verzií publikovaných s platnou npm provenance.[1][3]
Hlavné ponaučenie:
Provenance môže správne potvrdiť pôvod buildu, aj keď je samotný build škodlivý.
Treba tiež urobiť dôležité spresnenie: @tanstack/react-query samotný nebol v tomto incidente kompromitovaný. Zasiahnutý bol nezávislý code generator používaný s TanStack Query.[6][7]
Stav informácií: 31. augusta 2026.
TL;DR
| Otázka | Overená odpoveď |
|---|---|
| Napadnutý balík | @7nohe/openapi-react-query-codegen |
| Dátum | 28. augusta 2026 |
| Škodlivých verzií | 10 |
| Stabilných škodlivých verzií | 8 |
| Škodlivých prerelease | 2 |
@tanstack/react-query kompromitovaný? | Nie |
| Hlavný vektor | Nebezpečne navrhnutý GitHub Actions issue_comment release workflow |
| Potrebné heslo maintainera? | Nie |
| Potrebný long-lived npm token? | Nie |
| Publish oprávnenie | id-token: write + npm Trusted Publishing |
| Platná provenance? | Áno |
| Provenance = bezpečný kód? | Nie |
| Execution paths | binding.gyp, pri časti verzií aj preinstall |
| Hlavný payload | 3FWCvzduYZg.js |
Aktuálny latest | 3.0.2 |
| Severity | Critical, CVSS 9.6 |
| CVE | K 31. augustu advisory neuvádza známe CVE |
| Rodina | Aktivita spájaná s Mini Shai-Hulud / odvodenými variantmi |
| Istá atribúcia operátora? | Nie |
| Prioritná reakcia | Izolovať host a z čistého stroja rotovať všetky dostupné credentials |
Čo sa stalo 28. augusta?
GitHub Security Advisory GHSA-9pvf-vcx3-x239 uvádza 10 škodlivých verzií publikovaných približne medzi 20:00 a 20:21 UTC.[1]
Osem stabilných verzií:
0.5.4
0.5.5
1.6.3
1.6.4
2.2.1
2.2.2
3.0.3
3.0.4
a dva prerelease:
0.0.0-365d4eb738d3146583431948d3ba6e27a32556be
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab
Tag latest ukazoval na škodlivé 3.0.4 približne od 20:19:29 UTC do približne 22:51 UTC, keď bol vrátený na čisté 3.0.2.[1]
TanStack Query samotný nebol napadnutý
Formulácia:
TanStack Query hacked
je nepresná.
@7nohe/openapi-react-query-codegen je nezávislý projekt, ktorý generuje kód pre:
@tanstack/react-query
Ide o technologické prepojenie, nie oficiálny TanStack balík.
Oficiálna npm stránka @tanstack/react-query je samostatná a TanStack vo svojom májovom postmorteme výslovne uviedol Query medzi nezasiahnutými rodinami.[7][11]
Čo openapi-react-query-codegen robí?
Generuje napríklad:
- typed API clients,
- query keys,
queryOptions,infiniteQueryOptions,useQuery,useMutation,- suspense helpery,
- prefetch a SSR helpery.
Typický tok:
OpenAPI schema
↓
openapi-react-query-codegen
↓
TypeScript client
↓
TanStack Query hooks/options
Ide typicky o dev dependency, čo pri install-time malware neznamená nižšie riziko.
Ako rozšírený bol balík?
K 31. augustu npm ukazoval približne 155 tisíc stiahnutí týždenne.[6]
Je to dynamická metrika.
Dôležitejšie je, že codegen beží na vývojárskych strojoch a CI runneroch, často v prostredí s GitHub, SSH, cloud a deployment credentials.
Útok začal v GitHub Actions
Release workflow počúval na:
on:
issue_comment:
types: [created]
Samotný issue_comment nie je zraniteľnosť.
Nebezpečná bola kombinácia:
externý komentár
+
žiadna autorizácia autora
+
checkout PR kódu
+
spustenie kódu
+
id-token: write
+
publish
Jeden komentár mohol otvoriť release path
Workflow v zásade overoval, či komentár patril k pull requestu a jeho obsah bol presne npm publish.[1][2]
Chýbal spoľahlivý authorization gate pre roly ako:
OWNER
MEMBER
COLLABORATOR
Externý účet mohol otvoriť fork PR a komentárom dosiahnuť privilegovaný job.
Checkout forku zmenil input na code execution
Po checkoutovaní PR kódu workflow spustil:
pnpm install
Attacker-controlled obsah sa tak vykonal v release jobe s vysokými právami.
GitHub dlhodobo odporúča nespúšťať nedôveryhodný PR kód v privilegovaných workflows.[9]
id-token: write umožnil Trusted Publishing
Job mal:
permissions:
id-token: write
Je to legitímna permission pre npm Trusted Publishing cez OIDC.[10]
Problém nebol samotný OIDC.
Problém bol, že útočníkov kód bežal v jobe oprávnenom získať dôveryhodnú workload identity.
Nebolo potrebné ukradnúť heslo ani token
StepSecurity zdôrazňuje, že útočník nepotreboval maintainerovo npm heslo ani dlhodobý publish token.[2]
Starý threat model:
ukradnúť token
→ publish
Nový model:
ovplyvniť trusted workflow
→ workflow získa platnú identity
→ publish
Bezpečnostná hranica sa tak presúva z účtu do CI/CD architektúry.
Škodlivé release mali platnú provenance
Publikácie prebehli cez skutočný workflow a Trusted Publishing, preto mali platné provenance attestations.[1][3]
Provenance správne potvrdzovala:
tento artifact pochádza
z tohto repository
cez tento workflow
Nevyriešila však otázku, či kód checkoutovaný z PR bol legitímny.
Provenance nie je malware scanner
Provenance môže potvrdiť:
- pôvod buildu,
- identitu workflow,
- väzbu na source,
- chain of custody.
Automaticky nepotvrdzuje:
- bezpečný source code,
- autorizovaný PR,
- bezpečnú workflow logiku,
- absenciu malware.
Preto:
valid provenance
≠
safe package
npm Trusted Publishing používa OIDC na autentizáciu workloadu a provenance na doloženie pôvodu, nie ako univerzálny malware verdict.[10]
Prvý execution path: binding.gyp
Niektoré stabilné škodlivé verzie nemali viditeľný:
"preinstall": "..."
Namiesto toho pridali:
binding.gyp
GYP/Python evaluácia bola zneužitá tak, aby napokon spustila JavaScript payload cez systémový príkaz.[1][5]
Security scanner kontrolujúci iba lifecycle scripts v package.json by túto cestu mohol prehliadnuť.
Druhá cesta: preinstall
Ďalšie stabilné release pridali:
"preinstall": "node 3FWCvzduYZg.js"
Konkrétne:
0.5.5
1.6.4
2.2.2
3.0.4
Predchádzajúce stabilné verzie:
0.5.4
1.6.3
2.2.1
3.0.3
používali binding.gyp bez explicitného lifecycle scriptu.[1]
Dva prerelease boli odlišné
Dva 0.0.0-* prerelease obsahovali škodlivý preinstall, ale kvôli:
"files": ["dist"]
neboli odkazované payload files v tarballe.[1]
Všetkých 10 publikácií je klasifikovaných ako škodlivé, ale nejde o identické artefakty s rovnakou execution path.
Hlavný payload: 3FWCvzduYZg.js
Stabilné škodlivé tarbally obsahovali:
3FWCvzduYZg.js
s veľkosťou približne 4,4 až 6,4 MB podľa verzie.[1]
StepSecurity ukázal, že 0.5.4 narástla z približne 41 KB pri 0.5.3 na viac než 5,6 MB.[2]
Náhla zmena veľkosti balíka je užitočný supply-chain anomaly signal.
Čo payload robil počas behu?
StepSecurity detonoval zasiahnuté verzie v izolovaných GitHub-hosted runneroch.[2]
Pozorované správanie zahŕňalo:
Node spustí payload
→ curl stiahne Bun
→ Bun beží z /tmp/trinnyyyy-*
→ volá sa gh auth token
→ dotazuje sa Git Credential Manager
→ kontroluje ssh / scp
→ enumerujú sa procesy
→ spúšťa sa dočasný updater.py
Pozorovaný bol aj prístup k GitHub API a probing Google Cloud metadata hostname.[2]
Ide o malware zameraný na credentials.
Ktoré credentials považovať za ohrozené?
Skutočný rozsah závisí od oprávnení procesu.
Ak sa škodlivá verzia spustila, za potenciálne exponované považujte všetko, čo proces mohol čítať:
GitHub
npm
SSH
cloud
CI/CD
deployment
source repositories
Neznamená to, že každý secret bol na každom stroji skutočne exfiltrovaný.
Prečo je dev dependency nebezpečná
Argument:
je to len codegen
do browser bundle sa nedostane
nerieši install-time malware.
Payload stačí spustiť počas:
npm install
pnpm install
yarn install
Developer a CI prostredia často majú najcitlivejšie credentials z celého software lifecycle.
Package install je code-execution surface
Package managers podporujú hooks:
preinstall
install
postinstall
prepare
a native addon flows môžu spustiť node-gyp.
Inštalácia teda znamená:
dependency resolution
+
download
+
potenciálny code execution
Je isté, že išlo o TeamPCP?
JFrog, Socket a ďalší výskumníci spájajú payload s Mini Shai-Hulud a príbuznými variantmi.[3][4]
Presná atribúcia operátora však nie je verejne definitívne doložená.
Možné je:
- pokračovanie rovnakého aktéra,
- zvyškový prístup,
- reuse známeho malware,
- copycat.
JFrog túto neistotu výslovne spomína.[4]
Prečo sa Mini Shai-Hulud vracia?
Táto rodina kampaní cieli na credential theft, CI/CD, GitHub, package registries a propagáciu.[12]
Opakujúci sa model:
preniknúť do release cesty
→ získať publish authority
→ vydať dôveryhodne vyzerajúci package
→ spustiť sa na developer/CI hoste
→ hľadať ďalšie credentials
Májový útok na TanStack bol technicky iný
Dňa 11. mája 2026 bol zasiahnutý repository Router/Start.[11]
Útok kombinoval:
pull_request_target,- GitHub Actions cache poisoning,
- extrakciu OIDC tokenu z pamäte runnera.
Výsledok:
42 packages
84 škodlivých verzií
Nie je to rovnaký root cause ako 28. augusta.
Query bol čistý aj v máji
TanStack vo svojom oficiálnom postmorteme uviedol, že napadnutý bol iba Router/Start a Query patril medzi nezasiahnuté rodiny.[11]
Preto:
máj → Router/Start
august → nezávislý codegen pre Query
Ani jeden prípad neznamená kompromitáciu @tanstack/react-query.
Májový incident mal skutočný downstream dopad
OpenAI potvrdilo, že dve zariadenia zamestnancov boli májovým TanStack/Mini Shai-Hulud útokom zasiahnuté.[13]
OpenAI opísalo credential-focused aktivitu a obmedzenú exfiltráciu credential materiálu z časti repozitárov, ale nenašlo dôkazy o prístupe k user data ani kompromitácii produkčných systémov alebo IP.[13]
Krátke exposure window teda nemusí znamenať malý dopad.
August vs máj
Máj
fork PR
→ pull_request_target
→ poisoned cache
→ trusted release obnoví cache
→ OIDC token z pamäte
→ publish
August
fork PR
→ verejný komentár "npm publish"
→ privileged workflow checkoutuje PR
→ pnpm install spustí attacker code
→ job už má id-token: write
→ Trusted Publishing
Augustová cesta bola jednoduchšia.
Ako zistiť, či projekt bol zasiahnutý?
Prehľadajte všetky lockfiles, SBOM a historické CI záznamy pre všetkých 10 verzií.[1]
Kontrolujte:
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
SBOM
CI install logs
dependency caches
Aktuálny package.json nestačí.
Dôležité IOC
Verejne známe indikátory:[1][2][5]
3FWCvzduYZg.js
binding.gyp
is_it_this_simple.js
nu.js
/tmp/trinnyyyy-*/bun
/tmp/*/updater.py
Hľadajte aj neočakávané sťahovanie Bun, gh auth token, Git Credential Manager calls a nečakaný node-gyp v balíku, ktorý nepotrebuje native code.
Čo robiť po zasiahnutej inštalácii?
GitHub advisory a StepSecurity odporúčajú považovať host za potenciálne kompromitovaný.[1][2]
Minimálna reakcia:
1. zastaviť buildy
2. izolovať host
3. použiť oddelený čistý stroj
4. rotovať všetky dostupné credentials
5. invalidovať sessions
6. preveriť GitHub/npm/cloud audit logs
7. odstrániť dependency caches
8. zahodiť artifacts zo zasiahnutého runnera
9. rebuildovať z čistých vstupov
Nestačí rotovať iba npm token.
Ktoré verzie sú bezpečné?
GitHub advisory označuje 3.0.2 ako known-good a uvádza, že verzie publikované pred 28. augustom nie sú týmto incidentom zasiahnuté.[1]
StepSecurity uvádza čistých predchodcov:
0.5.3
1.6.2
2.2.0
3.0.2
Dňa 31. augusta npm znovu ukazuje:
latest = 3.0.2
Čo upstream opravil?
Podľa advisory:[1]
- odstránil
issue_commenttrigger, - release presunul na tag push,
- revoked npm Trusted Publisher,
- rotoval long-lived tokeny,
- vrátil
latestna3.0.2, - odstránil
predist-tag, - deprecated všetkých 10 škodlivých verzií,
- požiadal npm o odstránenie.
Snyk rovnako klasifikuje kompromitáciu ako Critical s CVSS 9.6, čo potvrdzuje závažnosť spustenia škodlivého kódu počas inštalácie.[8] Relevantné sú aj ďalšie hardening kroky, ktoré TanStack po májovom incidente zaviedol pre cache, workflows a release pipeline.[14]
Ako hardenovať GitHub Actions
- Nikdy nespúšťať untrusted PR code v privileged job.
- Pri comment-driven workflows overovať authorization aktéra.
id-token: writedať iba skutočnému publish jobu.- Oddeliť build od publish.
- Používať trusted trigger alebo approval.
- Third-party Actions pinovať na commit SHA.[9]
Ako hardenovať inštaláciu dependencies
Praktické kontroly:
- lockfiles,
- frozen installs,
- minimum release age/cooldown,
- monitoring nových publishov,
- package-size anomaly detection,
- lifecycle-script policy,
- sandboxované CI,
- obmedzenie outbound network,
- malicious-package scanning vedľa CVE,
- SBOM,
- minimálne credentials na runneroch.
npm Trusted Publishing zostáva užitočné.[10]
Ale:
Trusted Publishing
musí byť spojené s:
Trusted Workflow Design
Produkčný checklist
Dependencies
- Lockfile je povinný.
- CI blokuje neočakávané zmeny lockfile.
- Minimum release age/cooldown.
- Nová verzia nejde okamžite do produkcie.
- Sledujeme package-size zmeny.
- Kontrolujeme install scripts.
- Neočakávané
binding.gypvyvolá alert. - Malware scanning dopĺňa CVE scanning.
GitHub Actions
- Fork code nikdy nebeží privileged.
-
issue_commentmá authorization gate. -
pull_request_targetiba keď je nutný. -
GITHUB_TOKENmá least privilege. -
id-token: writelen kde je potrebné. - Publish vyžaduje trusted trigger.
- Build a publish sú oddelené.
- Actions sú pinované na SHA.
- Comment-driven automatizácia má negatívny test pre neautorizovaného používateľa.
- Release workflow nikdy necheckoutuje kód z nedôveryhodného forku.
npm
- Trusted Publisher je obmedzený na nevyhnutné workflows.
- Nemáme zbytočné long-lived publish tokeny.
- Publish monitorujeme realtime.
- Neplánovaný release vyvolá alert.
- Provenance overujeme, ale nepovažujeme za malware verdict.
- Máme runbook pre deprecation/revocation.
Runnery a endpointy
- CI runner je ephemeral.
- Workspace obsahuje minimum secretov.
- Cloud credentials sú short-lived.
- SSH keys majú minimálny scope.
- Outbound traffic je monitorovaný.
- Dependency install nemá široký prístup do infraštruktúry.
- Endpointy majú EDR/runtime monitoring.
- Host možno rýchlo izolovať.
Incident response
- Owner dependency incidentu je určený.
- Vieme historicky hľadať v lockfiles.
- Vieme rýchlo vyčistiť CI caches.
- Vieme invalidovať sessions.
- Máme mapu credentials dostupných runneru.
- Rotácia prebieha z clean machine.
- Kontrolujeme neautorizované npm publishes.
- Vyhodnocujeme GitHub audit logs.
Verdikt POLPROG
Kompromitácia @7nohe/openapi-react-query-codegen je veľmi dobrým príkladom toho, ako sa v roku 2026 menia software supply-chain attacks.
Útočník nemusel:
hacknúť npm
ukradnúť maintainerovo heslo
obísť 2FA
ukradnúť klasický publish token
Stačilo dostať untrusted code do workflow, ktorý už mal legitímnu publish identity.
Bezpečnostná hranica sa tak posúva k:
CI/CD
workflow triggers
OIDC
release authorization
dependency execution
Druhé ponaučenie je provenance.
Platná provenance tu nezlyhala. Správne potvrdila pôvod škodlivého buildu.
Tretie ponaučenie je presnosť.
TanStack Query samotný kompromitovaný nebol.
Napadnutý bol nezávislý nástroj jeho ekosystému.
K 31. augustu sú škodlivé verzie známe, advisory zverejnené, latest vrátené na 3.0.2 a release workflow upravený.[1][6]
Kľúčová otázka pre JavaScript tím teda nie je iba:
Používali sme tento balík?
Ale:
Môže sa v našom vlastnom release pipeline dostať nedôveryhodný input do jobu s publish authority?
Ak odpoveď nie je okamžite jasná, je čas auditovať GitHub Actions.

