Jeśli masz zainstalowane lightning==2.6.2 lub lightning==2.6.3 — traktuj maszynę jako skompromitowaną. Nie wystarczy odinstalować pakiet. Złośliwy kod uruchamia się przy każdym import lightning, nie przy instalacji — co oznacza że każde środowisko w którym pakiet był importowany jest dotknięte, niezależnie od tego czy instalacja była w sandboxie.
Kroki: zakończ wszystkie aktywne sesje, zrotuj GitHub PAT, tokeny GitHub Actions (ghs_), tokeny npm (npm_), klucze AWS, wszystkie zmienne środowiskowe zawierające poświadczenia. Sprawdź historię commitów pod kątem plików .claude/settings.json, .claude/router_runtime.js, .vscode/tasks.json i .github/workflows/format-check.yml — to są ślady po propagacji robaka.
Co się wydarzyło
30 kwietnia 2026 roku o 12:22 UTC na PyPI pojawiły się wersje 2.6.2 i 2.6.3 pakietu lightning — PyTorch Lightning, frameworka do trenowania modeli głębokiego uczenia z ponad 31 000 gwiazdkami na GitHubie i setkami tysięcy pobrań dziennie. Obie wersje zawierały złośliwy kod wstrzyknięty bezpośrednio do lightning/__init__.py.
Socket AI scanner oznaczył obie wersje jako złośliwe 18 minut po publikacji. PyPI poddało pakiet kwarantannie. Wersja 2.6.1 opublikowana 30 stycznia 2026 jest ostatnią czystą.
18 minut to imponująco szybka reakcja. Ale PyTorch Lightning ma setki tysięcy pobrań dziennie — przez 18 minut każde środowisko które zaktualizowało zależności lub uruchomiło pipeline CI/CD mogło zainstalować i zaimportować zainfekowaną wersję.
Dlaczego import, nie install, zmienia wszystko
Jest jeden szczegół techniczny który wymaga osobnego podkreślenia, bo większość artykułów go przeoczuje.
Złośliwy kod nie uruchamia się przy pip install. Uruchamia się przy import lightning.
Sandboxowane środowiska instalacyjne — popularne w CI/CD jako miara bezpieczeństwa — przechwytują złośliwe skrypty preinstall i postinstall. Nie przechwytują kodu wstrzykniętego do __init__.py modułu, bo ten uruchamia się nie podczas instalacji ale podczas wykonania programu.
W praktyce oznacza to: każdy notebook Jupyter, każdy skrypt treningowy, każdy job CI który wykonał import lightning na zainfekowanej wersji — uruchomił ładunek. Odinstalowanie pakietu po fakcie nie usuwa już wykonanych operacji. Poświadczenia zostały już wysłane na serwer sterujący.
Ładunek i jego zasięg
Mechanizm jest dwustopniowy. Złośliwy __init__.py pobiera środowisko uruchomieniowe Bun JavaScript i uruchamia 11 MB zaciemniony plik router_runtime.js. Ten plik jest — według analizy SafeDep — identyczny bajt po bajcie z execution.js z kampanii SAP CAP z poprzedniego dnia.
Zakres zbieranych danych jest szeroki: tokeny GitHub OAuth i PAT (ghp_, gho_), tokeny GitHub Actions (ghs_), tokeny npm (npm_), wszystkie zmienne środowiskowe procesu, klucze AWS przez sts:GetCallerIdentity i skanowanie AWS Secrets Manager, klucze SSH, historia powłoki, portfele kryptowalutowe.
Payload zawiera 703 odwołania do process i env, 463 do tokenów i uwierzytelnienia, 336 do repozytoriów. To nie jest przypadkowe zbieranie danych — to jest systematyczne targetowanie środowisk deweloperskich i CI/CD.
Robak propaguje się przez skradzione tokeny GitHub: pushe do 50 gałęzi per repozytorium, injekcja do pakietów npm które ofiara może publikować przez skradzione tokeny npm. Jeden skompromitowany deweloper staje się punktem wejścia do ekosystemu npm jego organizacji.
Szczegół który wszyscy pominęli
Jest jeden element tej kampanii który nie pojawił się w żadnym z głównych omówień, a który jest znaczący.
Złośliwy robak pushuje commity do repozytoriów ofiar jako claude@users.noreply.github.com — adres email kojarzony z Claude Code jako asystentem AI. Commits wyglądają jak standardowa aktywność Claude Code. Nie wyglądają jak attak.
Cel jest oczywisty: w środowiskach które używają Claude Code do kodowania, commit od claude@users.noreply.github.comjest nieodróżnialny od legalnej aktywności asystenta. Plik .claude/settings.json wstrzyknięty przez robaka wygląda jak plik konfiguracyjny Claude Code — bo tak właśnie jest nazwany.
Shai-Hulud nie tylko eksfiltruje dane przez GitHub. Maskuje swoją aktywność przez podszywanie się pod narzędzie AI do kodowania. W środowiskach które po ostatnich kampaniach TeamPCP audytują logi pod kątem nieznanych procesów — ten commit nie wyzwoli alertu.
Czwarta platforma w jednym tygodniu
Pisaliśmy o kampanii TeamPCP z 22 kwietnia — Checkmarx KICS przez Docker Hub, Bitwarden CLI przez npm. Pisaliśmy o Shai-Hulud przez Dependabot — narzędzia AI do kodowania jako cel. Teraz PyTorch Lightning na PyPI.
Ale to nie jest pełny obraz. SafeDep dokumentuje że w tym samym tygodniu Shai-Hulud pojawił się w czterech pakietach SAP na npm, w intercom-client@7.0.4 (przez skompromitowane konto maintainera który zainstalował pyannote-audio — pakiet z PyTorch Lightning jako zależnością transitive), w Packagist, w Ruby Gems i w modułach Go.
Socket ujmuje to precyzyjnie: "Po dwóch solidnych tygodniach praktycznie nieustannych ataków, tempo wygląda raczej na celowe i utrzymane niż oportunistyczne."
To nie jest już kampania w jednym ekosystemie. To jest operacja targetująca polyglot development environments — środowiska gdzie ta sama organizacja pisze modele ML w Pythonie, orkiestruje ruch HTTP przez Node.js, wdraża backend w Go i zarządza pakietami PHP. Każdy z tych ekosystemów był dotknięty w ciągu tygodnia.
Konta kompromitowane i zamknięte issue
Jest jeszcze jeden szczegół operacyjny który warto odnotować.
Konto GitHub pl-ghost — jeden z maintainerów projektu PyTorch Lightning — było skompromitowane w trakcie incydentu. Socket otworzył issue w repozytorium ostrzegając o kompromitacji. Issue zostało zamknięte w ciągu minuty przez pl-ghost, które następnie opublikowało mem "SILENCE DEVELOPER" w wątku.
W ciągu 70 minut pl-ghost przeprowadziło sześć operacji tworzenia i usuwania gałęzi w wielu repozytoriach Lightning-AI. Cztery gałęzie używały losowych dziesięcioznakowych nazw — ten sam wzorzec co robak Shai-Hulud przy weryfikacji dostępu do zapisu. Piąta próbowała podszywać się pod Dependabot z literówką: dependabot/fix-deds.
Zachowanie skompromitowanego konta maintainera aktywnie tłumiącego zgłoszenia bezpieczeństwa wpisuje się w ten sam wzorzec co ośmiomiesięczny uśpiony backdoor w Essential Plugin przez zakup portfolio wtyczek — konto z ustaloną historią i zaufaniem jako narzędzie do tłumienia wykrycia.
Środowiska ML jako miękki cel
Developer-tech zwraca uwagę na jeden strukturalny problem który czyni tę kampanię szczególnie skuteczną: data scientists i inżynierowie ML regularnie pobierają niezweryfikowane moduły Python z publicznych rejestrów do eksperymentalnych modeli, i często nie przechodzą przez te same szkolenia bezpieczeństwa co tradycyjni deweloperzy backendowi.
PyTorch Lightning jest narzędziem foundational dla skalowania eksperymentów głębokiego uczenia. Jego kompromitacja daje dostęp do klastrów obliczeniowych i zasobników chmurowych gdzie organizacje przechowują dane treningowe, wagi modeli, konfiguracje środowisk. To nie jest tylko kradzież tokenów GitHub — to jest dostęp do tego co organizacja zbudowała.
Intercom przez pyannote-audio: downstream effects
Najbardziej nieoczywista ofiara tej kampanii to intercom-client@7.0.4 — klient Intercom dla Node.js, używany przez setki organizacji SaaS. Kompromitacja nie była bezpośrednia. Wywodzi się z pyannote-audio — biblioteki Python do analizy dźwięku — która ma PyTorch Lightning jako zależność transitive.
Maintainer biblioteki zainstalował pyannote-audio lokalnie. Przy imporcie Lightning uruchomił się robak. Skradzione tokeny npm maintainera zostały użyte do opublikowania złośliwej wersji intercom-client przez automatyczny workflow CI publish.
Socket komentuje: "Jedna skompromitowana zależność może stać się mostem do kolejnych ekosystemów pakietów. To czyni tę sytuację szczególnie niepokojącą."
Podsumowanie
PyTorch Lightning był czystym pakietem przez lata. Shai-Hulud potrzebował jednej skompromitowanej sesji maintainera żeby zmienić to w 18 minut — od publikacji do wykrycia przez skanery. Przez te 18 minut każda automatyczna aktualizacja zależności w każdym pipeline CI/CD instalowała i importowała złośliwy kod.
Jeśli twoja organizacja trenuje modele, przetwarza dane audio lub wideo, albo ma jakiekolwiek Python ML pipelines w CI/CD — sprawdź teraz czy lightning==2.6.2 lub lightning==2.6.3 pojawiło się w którymkolwiek środowisku między 30 kwietnia godziną 12:22 UTC a godziną kwarantanny.
Źródła
Semgrep — pierwotna analiza z regułami YARA i szczegółami IOC: https://semgrep.dev/blog/2026/malicious-dependency-in-pytorch-lightning-used-for-ai-training/
Aikido Security — techniczne szczegóły ładunku i mechanizmu import-time: https://www.aikido.dev/blog/pytorch-lightning-pypi-compromise-mini-shai-hulud
Socket — analiza skompromitowanego konta pl-ghost i downstream effects przez intercom: https://socket.dev/blog/lightning-pypi-package-compromised
SafeDep — porównanie payload byte-for-byte z kampanią SAP i szczegóły claude@users.noreply.github.com: https://safedep.io/malicious-pytorch-lightning-pypi-compromise/
The Hacker News — pełny kontekst kampanii, Intercom i propagacja przez Packagist: https://thehackernews.com/2026/04/pytorch-lightning-compromised-in-pypi.html















































































