Joyfill npm: RAT uruchamiany przy imporcie pakietu
Dwa testowe pakiety Joyfill zawierały RAT ładowany przy imporcie modułu. Wyjaśniamy blockchainowy resolver C2, wpływ i plan reakcji.
- AUTOR
- Karol Rapacz / CEO Breachroad · OSCP · PNPT
- PUBLIKACJA
- 29 lipca 2026
- CZAS CZYTANIA
- 14 min czytania
- TEMAT
- Łańcuch dostaw
29 lipca 2026 roku badacze opisali kompromitację dwóch przedpremierowych wydań pakietów npm należących do ekosystemu Joyfill. W opublikowanych artefaktach znalazł się kod zdalnego dostępu, który uruchamiał się w chwili załadowania modułu przez aplikację, a nie jako klasyczny skrypt instalacyjny. To ważne rozróżnienie: popularne zabezpieczenie npm install --ignore-scripts mogło ograniczyć ryzyko związane ze skryptami cyklu życia, lecz nie blokowało kodu wykonywanego później przez require() lub import aplikacji.
Według analizy Socket opublikowanej 29 lipca, złośliwy kod znalazł się w:
@joyfill/[email protected];@joyfill/[email protected].
To konkretne wersje beta i release candidate. Nie ma podstaw, aby automatycznie uznawać za zainfekowane wszystkie wydania, cały projekt Joyfill albo każdą aplikację korzystającą z jego bibliotek. Organizacja powinna jednak sprawdzić nie tylko bezpośrednie zależności w package.json, ale też pliki blokad, lokalne cache, wewnętrzne proxy npm, obrazy kontenerowe i historyczne artefakty CI.
Co zostało potwierdzone
Socket przeanalizował opublikowane paczki i ustalił, że implant był obecny w wygenerowanych bundle’ach oraz widoczny w dołączonych mapach źródeł. To wskazuje, że złośliwy kod znalazł się w artefakcie przed publikacją albo podczas procesu budowania, a nie został doklejony wyłącznie przez rejestr po wysłaniu paczki. Sam ten ślad nie rozstrzyga jednak, jak doszło do kompromitacji: możliwe scenariusze obejmują przejęcie konta publikującego, tokena automatyzacji, środowiska CI, zależności procesu budowania lub stacji deweloperskiej. Badacze nie przypisali jednoznacznie pierwotnego wektora.
Kod uruchamiał podstawowy moduł Node.js RAT przy imporcie biblioteki. Implant potrafił zebrać informacje o systemie, utrzymywać komunikację ze zdalną infrastrukturą i wykonywać polecenia otrzymane od operatora. Badacze opisali również oddzielną, odłączoną gałąź procesu, która odwoływała się do adresu 23[.]27[.]13[.]43 i ścieżki /$/boot. Żądania miały charakterystyczny nagłówek Sec-V: A9-0135-3.
Najciekawszym elementem technicznym był mechanizm rozwiązywania adresów serwera dowodzenia przez publiczne sieci blockchain. Kod odpytywał wskazane źródła w ekosystemach Tron, Aptos i BNB Smart Chain, aby uzyskać aktualny punkt kontaktu. Blockchain nie był tu „serwerem malware”. Pełnił rolę publicznej, rozproszonej książki adresowej, z której implant mógł odzyskać pośrednią informację prowadzącą do infrastruktury operatora.
Dlaczego wykonanie przy imporcie zmienia model obrony
Wiele zespołów kojarzy ryzyko npm przede wszystkim z polami preinstall, install i postinstall. Wyłączenie tych hooków jest wartościową warstwą ochronną: utrudnia pakietowi automatyczne uruchomienie kodu podczas pobierania zależności. Nie gwarantuje jednak, że biblioteka jest bezpieczna.
JavaScript i Node.js z założenia wykonują kod inicjalizacyjny modułu przy jego pierwszym załadowaniu. Jeżeli złośliwa logika jest częścią głównego pliku biblioteki, aplikacja sama uruchomi ją podczas startu, renderowania komponentu, testu jednostkowego albo zadania budowania. W praktyce ekspozycja może więc nastąpić na:
- laptopie programisty uruchamiającego lokalny serwer;
- runnerze CI wykonującym testy lub budowanie;
- serwerze SSR, który ładuje paczkę po stronie backendu;
- narzędziu generującym dokumentację lub Storybook;
- procesie testowym mającym dostęp do sekretów środowiskowych;
- obrazie kontenerowym uruchomionym długo po pobraniu zależności.
To dlatego odpowiedź nie może skończyć się na sprawdzeniu logów npm install. Trzeba ustalić, gdzie i kiedy moduł został rzeczywiście załadowany.
Blockchain jako odporny resolver infrastruktury C2
Tradycyjny implant może mieć na stałe wpisaną domenę albo adres IP. Obrońcy mogą zablokować domenę, przejąć ją, dodać do filtrów DNS lub zgłosić hostingodawcy. Jeżeli kod zamiast tego odczytuje wartość z publicznej sieci blockchain, operator może próbować aktualizować wskazanie bez publikowania nowej wersji pakietu.
Nie oznacza to, że komunikacja jest niewidoczna. W środowisku przedsiębiorstwa pozostają obserwowalne:
- połączenia do bram API i węzłów blockchain, które są nietypowe dla procesu budowania;
- sekwencja odczytu wartości, a następnie połączenie do nowego hosta;
- uruchamianie procesów potomnych przez Node.js;
- rozbieżność między deklarowaną funkcją pakietu UI a jego ruchem sieciowym;
- nowe pliki, zadania trwałości lub odczyty katalogów z poświadczeniami.
Wniosek Breachroad: kontrola domen nie powinna opierać się wyłącznie na statycznej liście znanych C2. Lepsza reguła wykrywa zachowanie procesu: biblioteka layoutów nie ma uzasadnionej potrzeby odkrywania punktu końcowego przez trzy blockchainy i wykonywania poleceń systemowych.
Czy to DEV#POPPER lub PolinRider?
Socket wskazał podobieństwa do aktywności opisywanej jako DEV#POPPER oraz do rodziny narzędzi kojarzonych z PolinRider. Relacja The Hacker News z 29 lipca również omawia ten kontekst. Są to jednak podobieństwa kodu i sposobu działania, nie publicznie udowodniona atrybucja konkretnego operatora.
W raportowaniu incydentu warto rozdzielić trzy poziomy pewności:
- wysoką pewność, że wskazane wersje zawierały niepożądaną funkcję zdalnego dostępu;
- umiarkowaną ocenę pokrewieństwa implementacji z obserwowanymi wcześniej narzędziami;
- brak wystarczających danych, aby przypisać operację konkretnemu państwu, grupie lub osobie.
Takie rozdzielenie chroni zespół przed podejmowaniem decyzji na podstawie atrakcyjnej, ale niepotwierdzonej etykiety sprawcy.
Jak sprawdzić ekspozycję
Pierwszym krokiem jest wyszukanie dokładnych numerów wersji w plikach package-lock.json, npm-shrinkwrap.json, yarn.lock, pnpm-lock.yaml, manifestach SBOM i historii artefaktów. Sama nieobecność paczki w bieżącym branchu nie wystarcza: podatny build mógł powstać wcześniej, a gotowy kontener nadal działać.
Następnie należy przejrzeć:
- cache npm na stacjach i runnerach;
- wewnętrzne repozytoria Artifactory, Nexus, Verdaccio lub inne proxy;
- warstwy obrazów OCI i listę pakietów w aktywnych deploymentach;
- logi CI z okresu pobrania oraz uruchamiania testów;
- telemetrię EDR dla procesów Node.js i ich dzieci;
- DNS, proxy, NetFlow i egress firewall pod kątem infrastruktury opisanej w raporcie;
- użycie tokenów npm, GitHub, GitLab, chmurowych i rejestrowych dostępnych w potencjalnie dotkniętych środowiskach.
Nie wolno utożsamiać „pakiet został pobrany” z „RAT na pewno działał”. Pobranie potwierdza obecność artefaktu, a wykonanie wymaga dowodu w logach procesu, telemetrii lub zachowaniu sieciowym. Z drugiej strony brak pojedynczego IOC w proxy też nie wyklucza incydentu, ponieważ infrastruktura mogła być dynamicznie rozwiązywana.
Plan reakcji dla zespołu
Jeżeli odnajdziesz którąkolwiek z dwóch wersji, potraktuj środowisko jako potencjalnie dotknięte do czasu wyjaśnienia:
- zatrzymaj promocję związanych z nią buildów i odizoluj aktywne workloady;
- usuń wersję z manifestów, lockfile’ów, cache, proxy i bazowych obrazów;
- odtwórz artefakty z czystego, zweryfikowanego źródła zamiast „naprawiać” istniejący kontener;
- zinwentaryzuj sekrety dostępne dla procesu Node.js;
- unieważnij i wymień poświadczenia, których odczyt jest wiarygodnym scenariuszem;
- przejrzyj aktywność kont, tokenów i kluczy od momentu pierwszego możliwego wykonania;
- zachowaj próbki, lockfile, sumy, logi i obrazy do analizy powłamaniowej;
- sprawdź, czy zmodyfikowane artefakty nie zostały opublikowane dalej wewnątrz organizacji.
Rotacja wszystkich sekretów „na wszelki wypadek” może być operacyjnie kosztowna, ale zbyt wąska rotacja pozostawia furtkę. Priorytet powinny dostać tokeny o wysokich uprawnieniach: publikowanie npm, zapis do repozytoriów, rejestry kontenerowe, role chmurowe, klucze wdrożeniowe i sekrety produkcyjne widoczne dla runnera.
Jak ograniczyć podobne incydenty
Jedna kontrola nie zatrzyma całej klasy ataków. Skuteczny model łączy:
- pinowanie zależności i deterministyczne lockfile’y;
- kwarantannę nowych oraz przedpremierowych wersji przed dopuszczeniem do produkcji;
- porównywanie zawartości paczki z repozytorium i oczekiwanym buildem;
- generowanie SBOM dla każdego wydania;
- ograniczenie egressu runnerów i workloadów;
- krótkotrwałe poświadczenia zamiast stałych tokenów w zmiennych środowiskowych;
- odseparowanie procesu instalacji, testowania i publikowania;
- alarmy na nietypowy ruch sieciowy oraz procesy potomne Node.js;
- prywatne proxy z polityką dopuszczania wersji;
- ćwiczenia reakcji na kompromitację dostawcy.
Przedpremierowy sufiks nie powinien być traktowany jako niewinna cecha numeru. Wersje beta bywają instalowane przez zespoły testowe, a te często pracują w środowiskach połączonych z repozytoriami i systemami CI. Polityka może wymagać jawnej zgody na prerelease oraz automatycznie blokować jego promocję do produkcji.
Źródła a wnioski Breachroad
Źródła potwierdzają numery wersji, obecność kodu RAT, uruchomienie przy imporcie, użycie źródeł blockchain, wskazaną infrastrukturę i widoczność implantu w mapach źródeł. Nie potwierdzają publicznie pierwotnej drogi przejęcia procesu publikacji ani liczby faktycznie zainfekowanych organizacji.
Naszym wnioskiem jest priorytet dla przeglądu historycznych buildów oraz sekretów runnerów. To rekomendacja wynikająca z miejsca, w którym kod mógł się wykonać, a nie twierdzenie, że każdy użytkownik Joyfill utracił poświadczenia.
Co warto zrobić dziś
- wyszukaj dwie dokładne wersje we wszystkich lockfile’ach i SBOM;
- zablokuj ich pobieranie w firmowym proxy;
- sprawdź procesy Node.js, ruch blockchain/API i połączenia do IOC z raportu;
- wymień sekrety dostępne w środowiskach, w których potwierdzono wykonanie;
- wprowadź kwarantannę dla nowych prerelease’ów;
- przećwicz ścieżkę od wykrycia pakietu do wycofania wszystkich zależnych artefaktów.
Ataki na npm są problemem ludzi, procesu i architektury, nie tylko skanera zależności. Nasze szkolenia z cyberbezpieczeństwa i bezpiecznej pracy z kodem uczą zespoły deweloperskie i operacyjne rozpoznawania ryzyka łańcucha dostaw oraz prawidłowej eskalacji incydentu. Techniczne podstawy omawiamy także w przewodnikach o atakach na łańcuch dostaw oprogramowania i kampanii TeamPCP.
Jeśli potrzebujesz ocenić rzeczywistą ekspozycję organizacji, audyt bezpieczeństwa IT może objąć pipeline’y, repozytoria artefaktów, zarządzanie sekretami i telemetrię reakcji. Najważniejsze jest jednak teraz usunięcie wskazanych wersji oraz ustalenie, czy zostały tylko pobrane, czy również wykonane.
Jak podjąć decyzję o rotacji poświadczeń
Zakres rotacji powinien wynikać z przecięcia trzech danych: miejsca wykonania pakietu, czasu i dostępnych uprawnień. Jeżeli wersja znalazła się tylko w cache odłączonego proxy i nigdy nie została załadowana, dowody nie uzasadniają traktowania wszystkich kont firmy jako przejętych. Jeżeli test uruchomił moduł na współdzielonym runnerze z produkcyjną rolą chmurową, zakres jest znacznie szerszy.
Dla każdego środowiska warto utworzyć tabelę zawierającą:
- pierwszy i ostatni możliwy czas wykonania;
- tożsamość systemową procesu;
- zamontowane katalogi i sockety;
- widoczne zmienne środowiskowe;
- tokeny pobierane dynamicznie;
- systemy osiągalne z sieci runnera;
- dowody procesu, DNS i ruchu wychodzącego.
Na tej podstawie zespół klasyfikuje poświadczenia jako narażone, potencjalnie narażone albo poza zasięgiem. Decyzja musi być zapisana wraz z uzasadnieniem, ponieważ późniejsze nadużycie tokena może zmienić ocenę. Przydatny jest tu cykl Cyber Threat Intelligence: z publicznego raportu powstają wymagania zbierania danych, a z telemetrii — decyzja operacyjna.
Po odbudowaniu systemów należy upewnić się, że firmowe proxy nie przywróci zainfekowanej wersji z cache, a stary obraz nie wróci przez rollback. Retest obejmuje czysty lockfile, sumy nowego artefaktu, brak wersji w SBOM oraz obserwację aplikacji po starcie. W Akademii Breachroad zespoły mogą uzupełnić podstawy łańcucha dostaw i zarządzania dostępem bez pobierania podejrzanych próbek.
Najważniejszym wynikiem dochodzenia nie jest lista przeskanowanych repozytoriów. Jest nim udokumentowana odpowiedź na pytanie: czy kod się wykonał, jakie zaufanie odziedziczył i które trwałe drogi dostępu zostały unieważnione.


