28 sierpnia 2026 roku doszło do nowego ataku supply-chain na ekosystem npm. Tym razem zaatakowany został pakiet @7nohe/openapi-react-query-codegen, popularne narzędzie generujące kod TypeScript i hooki dla TanStack Query na podstawie specyfikacji OpenAPI.[1][2][3]
Atakujący nie musiał przejmować hasła maintainera do npm ani wykradać długowiecznego tokena publikacyjnego.
Wystarczyło wykorzystać błędnie skonfigurowany workflow GitHub Actions.
Repozytorium miało ścieżkę release uruchamianą zdarzeniem:
issue_comment
Jeżeli komentarz pod pull requestem miał dokładnie treść:
npm publish
workflow mógł przejść dalej bez sprawdzenia, czy osoba komentująca jest maintainerem, collaboratorem czy całkowicie zewnętrznym użytkownikiem GitHuba.[1][2]
Następnie pipeline:
sprawdzał kod z PR
→ wykonywał pnpm install
→ posiadał id-token: write
→ publikował przez npm Trusted Publishing
Rezultat był szczególnie niebezpieczny: 10 złośliwych wersji zostało opublikowanych z prawidłowym npm provenance.[1][3]
To kolejny incydent z 2026 roku pokazujący bardzo ważną prawdę:
Provenance może poprawnie potwierdzać, skąd pochodzi build, a jednocześnie ten build może być złośliwy.
Jeszcze ważniejsza korekta dotyczy samego TanStack Query.
@tanstack/react-query nie został skompromitowany w tym incydencie. Zaatakowany został zewnętrzny generator kodu, który tworzy hooki i queryOptions dla TanStack Query.[6]
To nie jest oficjalny pakiet TanStack.
Stan informacji: 31 sierpnia 2026 roku.
TL;DR
| Pytanie | Zweryfikowana odpowiedź |
|---|---|
| Co zostało zaatakowane? | @7nohe/openapi-react-query-codegen |
| Kiedy? | 28 sierpnia 2026 |
| Ile złośliwych wersji? | 10 |
| Ile stabilnych złośliwych wersji? | 8 |
| Ile złośliwych prerelease? | 2 |
Czy @tanstack/react-query został zhakowany? | Nie |
| Czy pakiet jest związany z TanStack Query? | Tak, generuje dla niego kod i hooki |
| Główny wektor | Błędny GitHub Actions issue_comment release workflow |
| Wymagane konto maintainera? | Nie |
| Wymagany skradziony długowieczny npm token? | Nie |
| Co dawało publish? | id-token: write + npm Trusted Publishing |
| Czy złośliwe wydania miały provenance? | Tak |
| Czy provenance gwarantuje bezpieczeństwo kodu? | Nie |
| Główne triggery malware | binding.gyp, a w części wersji także preinstall |
| Główny plik payloadu | 3FWCvzduYZg.js |
Aktualny latest | 3.0.2 |
Czy 3.0.2 jest wskazywany jako czysty? | Tak |
| Severity advisory | Critical, CVSS 9.6 |
| CVE | Brak znanego CVE w advisory na 31 sierpnia |
| Klasyfikacja | Embedded Malicious Code / supply-chain compromise |
| Rodzina kampanii | Badacze łączą incydent z Mini Shai-Hulud / pochodnymi |
| Czy operator został jednoznacznie potwierdzony? | Nie należy tego twierdzić z pełną pewnością |
| Najważniejsza reakcja | Izolacja hosta + rotacja wszystkich dostępnych credentiali z czystej maszyny |
Co dokładnie wydarzyło się 28 sierpnia?
GitHub Security Advisory GHSA-9pvf-vcx3-x239 opisuje 10 złośliwych wersji @7nohe/openapi-react-query-codegen opublikowanych pomiędzy około 20:00 a 20:21 UTC.[1]
Osiem z nich to stabilne wersje:
0.5.4
0.5.5
1.6.3
1.6.4
2.2.1
2.2.2
3.0.3
3.0.4
oraz dwa prerelease:
0.0.0-365d4eb738d3146583431948d3ba6e27a32556be
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab
Złośliwy latest wskazywał na 3.0.4 od około 20:19:29 UTC do około 22:51 UTC, kiedy tag przywrócono do czystego 3.0.2.[1]
Najważniejsza korekta: TanStack Query nie został skompromitowany
Nagłówki typu:
TanStack Query hacked
są w tym przypadku nieprecyzyjne.
Pakiet:
@7nohe/openapi-react-query-codegen
jest niezależnym projektem.
Jego zadaniem jest generowanie kodu dla:
@tanstack/react-query
na podstawie OpenAPI schema.[6]
To powiązanie technologiczne, nie własnościowe.
Aktualna strona npm @tanstack/react-query nadal wskazuje osobny oficjalny pakiet TanStack, a majowy postmortem TanStack również wyraźnie zaznaczał, że rodzina Query nie była objęta tamtym wcześniejszym kompromisem.[7][11]
Wniosek:
Incydent dotyczy narzędzia używanego z TanStack Query, nie samego TanStack Query.
Co robi openapi-react-query-codegen?
Pakiet generuje między innymi:
- typed API clients,
- query keys,
queryOptions,infiniteQueryOptions,useQuery,useMutation,useSuspenseQuery,- helpery prefetch i SSR.
Typowy workflow:
OpenAPI schema
↓
openapi-react-query-codegen
↓
TypeScript client
↓
TanStack Query hooks/options
To dev dependency.
I właśnie dlatego jest atrakcyjnym celem.
Dev dependency często uruchamia się:
- na laptopie programisty,
- w GitHub Actions,
- w release pipeline,
- w środowisku z tokenami,
- obok kodu źródłowego,
- w pobliżu credentiali cloud.
Nie musi trafić do browser bundle, aby wyrządzić szkody.
Jak popularny był pakiet?
31 sierpnia strona npm wskazywała około 155 tys. pobrań tygodniowo dla scoped package @7nohe/openapi-react-query-codegen.[6]
To metryka dynamiczna, więc nie należy traktować jej jako stałej wartości historycznej.
Ważniejszy jest charakter użycia.
Code generator jest instalowany w środowisku developerskim, czyli dokładnie tam, gdzie można znaleźć:
GitHub auth
npm credentials
SSH keys
cloud credentials
CI secrets
source code
Atak nie zaczął się od npm
Najważniejszy błąd znajdował się w GitHub Actions.
Release workflow nasłuchiwał:
on:
issue_comment:
types: [created]
i akceptował określony komentarz na pull requeście.[1]
Sam issue_comment nie jest automatycznie podatnością.
Problem powstał z kombinacji:
zewnętrzny komentarz
+
brak kontroli uprawnień autora
+
checkout kodu z PR
+
wykonanie kodu
+
id-token: write
+
publish
Każdy element osobno może być poprawny.
Łańcuch razem stworzył ścieżkę od anonimowego użytkownika GitHuba do publikacji w npm.
Jeden komentarz był triggerem release
Warunek workflow sprawdzał przede wszystkim, czy:
- komentarz dotyczył pull requesta,
- treść komentarza była równa
npm publish.
Brakowało kluczowego gate:
czy commenter należy do zaufanej grupy?
Na przykład:
OWNER
MEMBER
COLLABORATOR
Atakujący mógł więc przygotować kod w forku, otworzyć PR i uruchomić release commentem.
To nie jest problem samego issue_comment.
To problem braku authorization check przed wejściem w privileged workflow.
Checkout kodu z forka zmienił trigger w RCE
Samo uruchomienie workflow jeszcze nie daje złośliwemu PR możliwości wykonania kodu.
Kolejny krok był decydujący.
Pipeline checkoutował kod pull requesta, a następnie wykonywał:
pnpm install
Od tej chwili attacker-controlled repository content przestał być tylko danymi.
Stał się kodem wykonywanym wewnątrz release job.
To fundamentalna granica bezpieczeństwa:
untrusted code as data
vs
untrusted code executed in privileged context
GitHub od dawna ostrzega przed uruchamianiem kodu z niezaufanych PR w workflowach posiadających podwyższone uprawnienia.[9]
id-token: write otworzył drogę do npm
Workflow posiadał:
permissions:
id-token: write
To nie jest samo w sobie złe.
Jest potrzebne do OIDC-based Trusted Publishing.
npm Trusted Publishing pozwala CI opublikować pakiet bez przechowywania długowiecznego tokena npm.[10]
Zwykle jest to poprawa bezpieczeństwa.
W tym przypadku problem brzmiał:
kto może doprowadzić do uruchomienia uprzywilejowanego workflow?
Jeżeli niezaufany kod trafi do joba posiadającego prawo mintowania OIDC identity, Trusted Publishing zaczyna ufać legalnemu workflow wykonującemu nielegalny kod.
Nie trzeba było kraść hasła maintainera
StepSecurity podkreśla, że attacker nie potrzebował:
- hasła maintainera npm,
- long-lived npm publish tokena.
To ważna zmiana względem klasycznego account takeover.
Stary model zagrożenia:
ukradnij token
→ npm publish
Nowy model:
wpłyń na trusted workflow
→ workflow sam dostaje prawidłową tożsamość
→ publish
Przesunięcie granicy z konta maintainera do pipeline’u ma ogromne znaczenie dla DevSecOps.
Wszystkie złośliwe wydania miały prawidłowe provenance
Według GitHub advisory i analiz Socket publikacje przeszły przez prawdziwy workflow oraz npm Trusted Publishing, dlatego złośliwe wydania miały prawidłowe provenance/SLSA provenance.[1][3]
To nie znaczy, że provenance zawiodło kryptograficznie.
Wręcz przeciwnie.
Provenance prawidłowo mówiło:
ten artifact został opublikowany
przez ten workflow
z tego repozytorium
Problem:
workflow uruchamiał kod kontrolowany przez atakującego
Provenance nie jest skanerem malware
To jeden z najważniejszych wniosków z całego incydentu.
Provenance odpowiada na pytania typu:
- skąd pochodzi build,
- jaki workflow go zbudował,
- jakie repo jest źródłem,
- czy chain of custody jest zgodny.
Nie odpowiada automatycznie:
czy source code jest bezpieczny?
czy PR był autoryzowany?
czy workflow ma logiczną podatność?
czy artifact zawiera malware?
Dlatego:
valid provenance
≠
benign package
npm sam opisuje Trusted Publishing i automatyczną provenance jako mechanizmy potwierdzające pochodzenie, a nie jako pełny malware verdict.[10]
Pierwszy trigger malware: binding.gyp
Część złośliwych wydań nie miała klasycznego:
"preinstall": "..."
Zamiast tego do package root dodano:
binding.gyp
Node/npm może automatycznie uruchomić node-gyp rebuild, gdy package wygląda jak native addon.
Złośliwy binding.gyp wykorzystywał evaluator Pythona w GYP do dotarcia do os.system() i uruchomienia JavaScript payloadu.[1][5]
To szczególnie ważne dla skanerów.
Reguła:
szukaj wyłącznie preinstall/postinstall
nie wystarcza.
Drugi trigger: jawny preinstall
W kolejnej grupie stabilnych wydań pojawił się także:
"preinstall": "node 3FWCvzduYZg.js"
Dotyczyło to:
0.5.5
1.6.4
2.2.2
3.0.4
Pierwsze wersje:
0.5.4
1.6.3
2.2.1
3.0.3
wykorzystywały binding.gyp bez jawnego install scriptu.[1]
To świadome zróżnicowanie triggerów utrudnia prostą detekcję opartą na jednym IOC.
Dwa prerelease były złośliwe, ale inaczej
Dwa 0.0.0-* prerelease miały złośliwy preinstall, lecz przez ustawienie:
"files": ["dist"]
payload files nie znalazły się w tarballu.[1]
To oznacza, że nie należy traktować wszystkich 10 artifactów jako bitowo identycznych lub wykonujących identyczną ścieżkę.
Wszystkie są klasyfikowane jako złośliwe publikacje.
Ale osiem stabilnych wersji ma pełniejszy, potwierdzony zestaw triggerów i payloadów.
Główny payload: 3FWCvzduYZg.js
Stabilne złośliwe tarballe zawierały plik:
3FWCvzduYZg.js
o rozmiarze około 4,4–6,4 MB zależnie od wydania.[1]
Wersja 3.0.4 miała payload o rozmiarze ponad 6 MB i jawny preinstall.[2]
Duży, silnie obfuscated JavaScript w małym codegen package jest sam w sobie sygnałem anomalii.
StepSecurity zwraca uwagę, że 0.5.4 urósł z około 41 KB w 0.5.3 do ponad 5,6 MB.[2]
Nagły package-size delta jest bardzo przydatnym sygnałem supply-chain.
Co payload robił w runtime?
StepSecurity uruchomił złośliwe wersje na izolowanych GitHub-hosted runners.[2]
Dla 3.0.4 obserwowano między innymi:
Node uruchamia payload
→ curl pobiera Bun
→ Bun startuje z /tmp/trinnyyyy-*
→ wykonywane jest gh auth token
→ odpytywany jest Git credential manager
→ sprawdzane są ssh / scp
→ enumerowane są procesy
→ uruchamiany jest tymczasowy updater.py
Obserwowano także kontakt z GitHub API i próby dotarcia do Google Cloud metadata hostname.[2]
To jest credential-focused malware, nie zwykły cryptominer.
Zakres potencjalnie dostępnych sekretów
Jeżeli malware działa jako proces użytkownika lub CI runnera, jego realny zakres zależy od środowiska.
Może potencjalnie zobaczyć to, do czego proces ma dostęp:
GitHub auth
npm credentials
SSH keys
cloud env vars
CI/CD secrets
source repositories
deployment credentials
Nie oznacza to, że każdy z tych sekretów został skradziony na każdym hoście.
Prawidłowe sformułowanie brzmi:
Jeżeli złośliwa wersja została wykonana, wszystkie credentials dostępne dla procesu należy uznać za potencjalnie narażone.
Dlaczego dev dependency jest równie groźny jak runtime dependency?
Frontend developer może pomyśleć:
to tylko codegen
nie trafia do produkcyjnego bundle
To błędny model bezpieczeństwa.
Malware potrzebuje wykonać się podczas:
npm install
pnpm install
yarn install
Nie potrzebuje trafić do kodu klienta.
Dev dependency może być nawet cenniejszym celem, bo działa na maszynach:
- z SSH,
- z
gh, - z cloud CLI,
- z
.npmrc, - z repo,
- z CI tokens.
npm install jest powierzchnią wykonania kodu
Package managers od dawna wspierają lifecycle scripts.
Przykłady:
preinstall
install
postinstall
prepare
Dodatkowo native addon flows mogą uruchamiać narzędzia takie jak node-gyp.
Dlatego installation jest w praktyce:
dependency resolution
+
download
+
potential code execution
Nie jest to wyłącznie „kopiowanie bibliotek do node_modules”.
To jeden z powodów, dla których supply-chain security musi działać przed lub w trakcie instalacji, a nie dopiero na finalnym artifact.
Czy to na pewno TeamPCP?
Badacze JFrog, Socket i inni łączą malware z rodziną Mini Shai-Hulud i jej późniejszymi wariantami.[3][4]
JFrog zwraca jednak uwagę na ważną niepewność dotyczącą operatora.
Podobieństwo kodu, technik i kampanijnych markerów może wskazywać na:
- kontynuację tej samej operacji,
- wykorzystanie pozostałego dostępu,
- reuse publicznie dostępnego malware,
- copycat.
Dlatego nie będziemy pisać:
na 100% zrobił to konkretny operator
jeżeli publiczne dowody nie rozstrzygają tego jednoznacznie.
Dlaczego nazwa Mini Shai-Hulud wraca?
Mini Shai-Hulud to rodzina/kampania supply-chain skupiona na:
- credential theft,
- CI/CD,
- npm,
- GitHub,
- automatycznej propagacji.
W maju 2026 badacze obserwowali kompromisy obejmujące TanStack, Mistral, UiPath i kolejne pakiety.[12]
W sierpniu podobne lub pochodne techniki nadal pojawiają się w nowych kompromisach.
Najważniejsze nie jest logo kampanii.
Najważniejszy jest powtarzający się model:
wejdź przez pipeline
→ ukradnij/uprawnij publish
→ opublikuj zaufany artifact
→ wykonaj malware na kolejnych developer machines
→ szukaj następnych credentiali
Majowy TanStack attack był innym incydentem
11 maja 2026 kompromis dotyczył repozytorium TanStack Router/Start.[11]
Atakujący połączył:
pull_request_targetPwn Request,- GitHub Actions cache poisoning,
- odczyt OIDC tokena z pamięci runnera.
Efektem było:
42 pakiety
84 złośliwe wersje
To nie jest ten sam techniczny root cause co 28 sierpnia.
W maju TanStack Query także był czysty
Oficjalny TanStack postmortem po audycie stwierdził:
- affected: Router/Start repo,
- unaffected: Query, DB, Store, AI, Table, Form, Virtual i inne rodziny.
To ważne, bo w 2026 wystąpiły co najmniej dwa incydenty, które można powierzchownie opisać jako:
TanStack supply-chain attack
ale w żadnym z nich nie należy automatycznie stwierdzać:
@tanstack/react-query był zainfekowany
W sierpniu zaatakowano zewnętrzny codegen.
W maju zaatakowano Router/Start monorepo.
Majowy incydent pokazał realny downstream impact
OpenAI potwierdziło, że dwie maszyny pracowników zostały dotknięte majowym atakiem TanStack/Mini Shai-Hulud.[13]
Firma podała między innymi:
- credential-focused activity,
- ograniczoną eksfiltrację materiałów credentialowych z części repozytoriów,
- brak dowodów na dostęp do user data,
- brak dowodów na kompromis produkcyjnych systemów lub IP,
- rotację credentiali i certyfikatów podpisujących jako środek ostrożności.
To pokazuje, dlaczego kilka minut ekspozycji złośliwego package może być istotne nawet dla bardzo dojrzałych organizacji.
Czym sierpniowy atak różni się od majowego?
Maj
fork PR
→ pull_request_target
→ poisoned cache
→ trusted release restores cache
→ OIDC token extracted from runner memory
→ publish
Sierpień
fork PR
→ public issue_comment "npm publish"
→ privileged workflow checks out PR
→ pnpm install executes attacker code
→ workflow already has id-token: write
→ Trusted Publishing
Sierpniowa ścieżka jest prostsza.
Nie wymaga skomplikowanego cache poisoning.
To właśnie powinno niepokoić najbardziej.
Jak sprawdzić, czy projekt jest dotknięty?
Najpierw sprawdź lockfile i SBOM.
Szukaj dokładnie wersji:
0.5.4
0.5.5
1.6.3
1.6.4
2.2.1
2.2.2
3.0.3
3.0.4
0.0.0-365d4eb738d3146583431948d3ba6e27a32556be
0.0.0-ec7876d6c917dad516ba69bbfafc948b834bf0ab
Sprawdź:
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
SBOM
CI install logs
dependency cache
Nie wystarczy sprawdzić obecnego package.json.
Floating range mógł historycznie rozwiązać się do złośliwej wersji, a potem wrócić do czystego latest.
Najważniejsze IOCs
Publiczne IOCs obejmują:[1][2][5]
3FWCvzduYZg.js
binding.gyp
is_it_this_simple.js
nu.js
/tmp/trinnyyyy-*/bun
/tmp/*/updater.py
Dodatkowo warto szukać:
- nagłego downloadu Bun podczas install,
- wywołań
gh auth token, - nietypowego
git credential-manager, - outbound traffic do GitHub release assets podczas instalacji,
- nieoczekiwanego node-gyp w package, który nie potrzebuje native addon.
IOC nie powinien być jedyną metodą detekcji.
Payload może zmienić nazwę.
Behavioral detection jest ważniejsza.
Co zrobić, jeśli złośliwa wersja została zainstalowana?
Oficjalne advisory i StepSecurity rekomendują traktowanie hosta jako potencjalnie skompromitowanego.[1][2]
Minimalny response:
1. zatrzymaj buildy
2. odizoluj host
3. użyj osobnej czystej maszyny
4. rotuj wszystkie dostępne sekrety
5. unieważnij aktywne sesje
6. sprawdź GitHub/npm/cloud audit logs
7. usuń dependency caches
8. odrzuć artifacts z zainfekowanego runnera
9. odbuduj środowisko z czystego źródła
Nie rotuj tylko npm tokena.
Jeżeli proces widział więcej, zakres rotacji musi być szerszy.
Jakie wersje są bezpieczne?
GitHub advisory wskazuje 3.0.2 jako patched/known-good i stwierdza, że żadna wersja opublikowana przed 28 sierpnia nie była objęta tym incydentem.[1]
StepSecurity wskazuje czyste poprzedniki dla poszczególnych linii:
0.5.3
1.6.2
2.2.0
3.0.2
31 sierpnia npm ponownie wskazuje:
latest = 3.0.2
Jeśli nie masz powodu utrzymywać starszej linii, oficjalne advisory prowadzi do 3.0.2.
Co naprawił maintainer?
Według GitHub advisory upstream zastosował między innymi:[1]
- usunięcie
issue_commenttrigger, - publikację po tag push,
- revocation npm trusted publisher,
- rotację long-lived tokens,
- przywrócenie
latestdo3.0.2, - usunięcie
predist-tag, - deprecację wszystkich 10 złośliwych wersji,
- zgłoszenie removal do npm security.
To prawidłowy kierunek:
public interaction
nie powinno być bezpośrednim gatewayem do:
production publish identity
Snyk również klasyfikuje kompromitację jako Critical i wskazuje CVSS 9.6, co potwierdza wagę wykonania złośliwego kodu podczas instalacji.[8] Warto też odnieść się do zmian wprowadzonych przez TanStack po majowym incydencie, w tym dalszego hardeningu workflowów, cache i release pipeline.[14]
Jak zabezpieczyć GitHub Actions?
Nigdy nie wykonuj kodu z niezaufanego PR w privileged job
GitHub zaleca oddzielać:
untrusted build
od:
trusted action
Sprawdzaj actor authorization
Dla comment-driven automation potrzebny jest jawny gate.
Minimalizuj permissions
Jeśli job nie publikuje:
id-token: write
nie powinno istnieć.
Rozdziel build od publish
Najbezpieczniej:
untrusted PR CI
↓
artifact jako dane
↓
review / trusted trigger
↓
release
Pin GitHub Actions do commit SHA
Tag akcji również jest częścią supply chain.
Jak zabezpieczyć npm dependency install?
Nie ma jednego magicznego przełącznika.
Praktyczny zestaw:
- lockfiles,
- frozen lockfile installs,
- package release cooldown/minimum age,
- monitoring nowych publishów,
- analiza package-size delta,
- lifecycle-script policy,
- sandboxowane CI,
- outbound network policy,
- SCA + malicious-package detection,
- SBOM,
- minimalne credentials na runnerze.
npm Trusted Publishing nadal ma sens.[10]
Ale:
Trusted Publishing
musi być połączone z:
Trusted Workflow Design
Produkcyjna checklista po tym incydencie
Dependencies
- Używamy lockfile.
- CI odrzuca nieoczekiwane zmiany lockfile.
- Mamy minimum release age/cooldown.
- Nowa wersja package nie wpada automatycznie do produkcji.
- Monitorujemy nagłe package-size changes.
- Sprawdzamy install scripts.
- Sprawdzamy
binding.gypw nietypowych paczkach. - Skanujemy malicious packages, nie tylko CVE.
GitHub Actions
- Nie wykonujemy fork code w privileged context.
-
issue_commentma authorization gate. -
pull_request_targetjest używany tylko, gdy naprawdę potrzebny. -
GITHUB_TOKENma minimalne permissions. -
id-token: writema tylko publish job. - Publish wymaga trusted trigger.
- Build i publish są rozdzielone.
- Actions są przypięte do SHA.
- Comment-driven automation ma test negatywny dla użytkownika bez uprawnień.
- Release workflow nie checkoutuje kodu z niezaufanego forka.
npm
- Trusted Publisher jest przypisany do minimalnej liczby workflows.
- Nie trzymamy zbędnych long-lived publish tokens.
- Publikacje są monitorowane w czasie rzeczywistym.
- Alerts obejmują nowe wersje poza planowanym release.
- Provenance jest weryfikowane, ale nie traktowane jako malware verdict.
- W przypadku incydentu potrafimy natychmiast deprecate/revoke.
Runnery i stacje developerów
- CI runner jest ephemeral.
- Workspace nie zawiera niepotrzebnych sekretów.
- Cloud credentials są short-lived.
- SSH keys mają minimalny scope.
- Outbound traffic jest monitorowany.
- Dependency install nie ma otwartego dostępu do całej infrastruktury.
- Developer endpoints mają EDR/runtime monitoring.
- Potrafimy szybko odizolować host.
Incident response
- Znamy ownera dependency incident response.
- Potrafimy przeszukać lockfiles historycznie.
- Potrafimy wyczyścić CI caches.
- Potrafimy unieważnić sessions.
- Mamy mapę credentiali dostępnych z runnerów.
- Rotacja odbywa się z clean machine.
- Sprawdzamy nieautoryzowane npm publishes.
- Sprawdzamy GitHub audit logs po rotacji.
Werdykt POLPROG
Incydent @7nohe/openapi-react-query-codegen jest jednym z najlepszych przykładów tego, jak zmienia się software supply-chain security w 2026 roku.
Atakujący nie musiał:
zhakować npm
ukraść hasła maintainera
przejąć 2FA
ukraść klasycznego publish tokena
Wystarczyło, że release workflow pozwalał niezaufanemu użytkownikowi doprowadzić do wykonania jego kodu w jobie posiadającym prawa do Trusted Publishing.
To ogromna różnica.
Klasyczna ochrona konta nadal jest potrzebna.
Ale współczesna granica bezpieczeństwa przesuwa się do:
CI/CD graph
workflow triggers
cache
artifacts
OIDC
release authorization
dependency execution
Drugi ważny wniosek dotyczy provenance.
Valid provenance jest cenne.
W tym incydencie jednak prawidłowo potwierdzało ono pochodzenie złośliwego builda.
To nie wada kryptografii.
To konsekwencja błędnego zaufania do workflow.
Trzeci wniosek dotyczy nazewnictwa.
TanStack Query nie został w tym incydencie skompromitowany.
Zaatakowany pakiet generuje kod dla TanStack Query, ale jest niezależnym projektem.
Takie rozróżnienie ma znaczenie, bo w security nie można przenosić winy lub zakresu incydentu na cały ekosystem tylko dlatego, że biblioteka pojawia się w nazwie lub dependency graph.
Na 31 sierpnia:
malicious versions: znane
advisory: opublikowane
latest: przywrócone do 3.0.2
upstream workflow: zmieniony
Ale najważniejsze pytanie dla każdego zespołu JavaScript nie brzmi:
Czy używaliśmy tego konkretnego pakietu?
Tylko:
Czy nasz własny release pipeline ma podobną ścieżkę, w której niezaufany input może dotrzeć do joba z prawem publikacji?
Jeżeli odpowiedź nie jest natychmiast oczywista, warto zrobić audyt GitHub Actions teraz.

