Reklama
Reklama
Reklama
  • WIADOMOŚCI
  • WAŻNE

Złośliwy kod z zaufanego źródła. Jak przestępcy wykorzystują npm

Programista analizuje na monitorach zależności npm, proces publikacji pakietów i alert wskazujący na wykrycie złośliwego kodu.
Zaufane źródło nie gwarantuje, że opublikowany kod jest bezpieczny. Przypadki AsyncAPI i Jscramblera pokazują, że złośliwe paczki mogą trafić do npm także przez legalne procesy publikacji.
Autor. CyberDefence24/ChatGPT

Programiści nie tworzą każdej funkcji aplikacji od zera. Pobierają gotowe elementy z npm, publicznego katalogu oprogramowania dla JavaScriptu. 8 lipca 2026 roku ukazał się npm 12.0.0, który domyślnie wstrzymuje skrypty uruchamiane przez instalowane dodatki. Kilka dni później incydenty Jscramblera i AsyncAPI pokazał, że szkodliwy kod może poczekać do późniejszego uruchomienia programu albo przejść przez prawdziwy, wcześniej zaufany proces publikacji. Wyjaśniamy, co więc naprawdę oznacza informacja, że paczka pochodzi z właściwego źródła.

Poniżej rozkładamy ten problem na części: czym jest paczka npm, jak trafia do katalogu, co potwierdza informacja o jej źródle i czego nie potrafi ocenić. Teza jest prosta: taki zapis pomaga odtworzyć drogę pliku, ale nie sprawdza, czy znajdujący się w nim kod działa bezpiecznie.

Czym jest npm i dlaczego ma znaczenie

npm to internetowy katalog oraz program służący do pobierania gotowego kodu. Paczka może być niewielkim dodatkiem, narzędziem uruchamianym z terminala albo biblioteką używaną przez dużą aplikację. Gdy projekt potrzebuje jej do działania, paczka staje się zależnością. Jedna popularna zależność może więc pośrednio znaleźć się w tysiącach produktów.

Reklama

Kod paczki zwykle powstaje w repozytorium, najczęściej na GitHubie. Repozytorium przechowuje pliki i historię zmian. Commit to pojedynczy zapis zmiany, a branch, czyli gałąź, pozwala rozwijać osobną wersję kodu. Na końcu automatyczny proces uruchamia testy, buduje paczkę i wysyła ją do npm. Sam produkt ma postać folderu lub archiwum opisanego plikiem package.json.

Co naprawdę potwierdza źródło paczki


Od 2023 roku wydawca może dołączyć do paczki cyfrowy zapis jej pochodzenia. Łączy on opublikowany plik z konkretnym repozytorium, zmianą w kodzie i procesem użytym do przygotowania wydania. Odbiorca może sprawdzić, czy paczka rzeczywiście wyszła z deklarowanego projektu i który automatyczny proces ją opublikował. Nie jest to jednak badanie zawartości pliku.

Trusted Publishing, czyli zaufane publikowanie, chroni samo logowanie automatyzacji do npm. Zamiast stałego tokenu, działającego podobnie do długo ważnego hasła, npm przyjmuje krótkotrwałe poświadczenie OIDC wystawione dla konkretnego, wcześniej zatwierdzonego procesu. Takiego cyfrowego biletu nie trzeba przechowywać i po zakończeniu zadania traci on ważność. To ogranicza ryzyko kradzieży stałego klucza, ale nie naprawi przejętego repozytorium ani konta automatyzacji.

Inne zabezpieczenia odpowiadają na inne pytania. Podpis rejestru pomaga wykryć zmianę paczki po jej opublikowaniu. SBOM jest listą składników programu, a narzędzia typu SCA porównują użyte wersje z informacjami o znanych podatnościach. Skaner złośliwego oprogramowania szuka podejrzanych wzorców lub zachowań. Żaden z tych mechanizmów sam nie daje pełnej odpowiedzi na pytanie, czy cały kod jest bezpieczny.

Reklama

AsyncAPI: prawdziwy proces opublikował złośliwy kod

Najlepiej pokazuje to incydent AsyncAPI z 14 lipca 2026 roku. Według oficjalnego raportu projektu sprawca rozpoczął od fali spamowych pull requestów, czyli propozycji zmian w kodzie. Ich liczba miała zasłonić jedno naprawdę niebezpieczne zgłoszenie.

Atak wykorzystał starszą automatyzację opartą na pull\_request\_target. Taki mechanizm może obsługiwać zmiany nadesłane z zewnątrz, a jednocześnie działać z uprawnieniami głównego projektu. Nadaje się do prostych czynności, na przykład dodawania etykiet, ale nie powinien uruchamiać kodu obcej osoby. GitHub ostrzega, że ten tryb może mieć dostęp do tokenu i sekretów repozytorium.

Sprawca przejął dane konta automatyzacji asyncapi-bot. Konto miało szerokie uprawnienia, mogło omijać część ochrony gałęzi i działać w kilku repozytoriach. Napastnik wprowadził szkodliwy kod bezpośrednio do gałęzi wydaniowych, po czym legalne procesy opublikowały pięć złośliwych wersji przez OIDC Trusted Publishing. Do paczek dołączono prawidłową informację o źródle, ponieważ rzeczywiście pochodziły już z właściwego repozytorium i właściwej automatyzacji. Przejęty został punkt, któremu system ufał.

Złośliwy fragment nie uruchamiał się podczas samej instalacji. Wykonywał się dopiero wtedy, gdy aplikacja ładowała bibliotekę przez require lub import. Dla osoby spoza programowania oznacza to, że paczka mogła zostać pobrana bez widocznego zdarzenia, a kod ruszał dopiero, gdy program zaczął z niej korzystać.

Reklama

Co zmienił npm 12

Paczka może zawierać zadania preinstall, install i postinstall. Są wykonywane przed instalacją, w jej trakcie lub po zakończeniu i mogą służyć do przygotowania plików albo kompilacji. Dla napastnika były wygodne, ponieważ uruchamiały kod automatycznie po dodaniu zależności. npm opisuje je jako skrypty cyklu życia paczki.

W npm 12 skrypty zależności są domyślnie zatrzymywane, dopóki główny projekt nie dopuści ich w ustawieniu allowScripts. Administrator może zatwierdzić konkretną paczkę albo zapisać odmowę, a zgoda zwykle dotyczy wskazanej wersji. Kontrola obejmuje skrypty instalacyjne, lecz nie każdy plik JavaScript uruchamiany później przez aplikację, test lub narzędzie w terminalu. npm 12 zamyka więc ważne wejście, ale nie analizuje całego zachowania paczki.

Jscrambler: gdy kod czeka na późniejsze uruchomienie

W przypadku Jscramblera początek ataku był inny. Według oficjalnego raportu firmy napastnik przejął komputer dewelopera oraz dane dostępu do GitHuba i npm. Następnie wykorzystał GitHub Actions do kradzieży osobnego tokenu publikacyjnego. Za jego pomocą wysłał do npm pięć złośliwych wersji paczki jscrambler. Nie ma publicznego potwierdzenia, że miały one prawidłową informację o pochodzeniu.

Pierwsze wersje uruchamiały kod przez preinstall, czyli podczas instalacji. W późniejszych wydaniach sprawca przeniósł działanie do chwili użycia narzędzia CLI, programu obsługiwanego poleceniami w terminalu. Zespół początkowo unieważnił niewłaściwe poświadczenie, dlatego publikacje trwały. Dopiero cofnięcie tokenu skradzionego z automatyzacji zatrzymało kolejne wydania. Incydent pokazuje, że ochrona samej instalacji i zmiana jednego hasła mogą nie wystarczyć.

Problem nie zakończył się na tych dwóch przypadkach. 4 sierpnia 2026 roku Microsoft opisał kampanię ChainDrop, w której złośliwe wydania objęły ponad 400 paczek wielu niezależnych autorów. Atak wykorzystywał skradzione dane publikacyjne, skrypty preinstall, a także możliwość przejęcia legalnej drogi wydawniczej opartej na GitHub Actions i OIDC.

Gdzie przerwać łańcuch

Każdy etap ma własny punkt kontrolny. Jedno oznaczenie przy paczce nie zastąpi ochrony kodu, procesu publikacji i środowiska, które później uruchamia zależność.

Źródło kodu. Gałęzie wydaniowe powinny blokować wymuszone przepisywanie historii, wymagać przeglądu zmian i obejmować tymi zasadami także administratorów oraz konta automatyzacji. GitHub pozwala wyłączyć force-push i wymagać zatwierdzeń przed zmianą chronionej gałęzi. Bot powinien mieć dostęp tylko do tych repozytoriów, których naprawdę potrzebuje.

Publikacja i instalacja. Stałe tokeny warto zastępować Trusted Publishing, ale ważne wydania powinny wymagać dodatkowej zgody człowieka. Zespół powinien sprawdzać nie tylko obecność informacji o źródle, lecz także wskazane repozytorium, gałąź, zmianę i proces. W npm 12 skrypty zależności należy pozostawić wyłączone i zatwierdzać tylko uzasadnione wyjątki dla konkretnych wersji.

Działanie programu. Maszyny budujące aplikacje powinny być odizolowane i mieć dostęp wyłącznie do niezbędnych sekretów oraz połączeń sieciowych. Po instalacji warto obserwować, czy Node.js albo Bun, czyli środowiska wykonujące JavaScript, nie uruchamiają nietypowych programów i nie łączą się z nieznanymi serwerami. Po incydencie trzeba zmienić wszystkie powiązane klucze, wyczyścić pamięci podręczne i ponownie zbudować produkty ze sprawdzonego kodu.

Reklama

Źródło paczki to nie test bezpieczeństwa

Jscrambler i AsyncAPI pokazują dwa różne punkty awarii. W pierwszym przypadku sprawca ukradł dane pozwalające publikować zmienione paczki. W drugim przejął zaufane konto i gałęzie projektu, dlatego oficjalny proces poprawnie opisał drogę szkodliwego wydania. npm 12 ogranicza automatyczne wykonanie podczas instalacji, ale nie zatrzymuje kodu czekającego na późniejsze użycie. Informacja o pochodzeniu nadal jest cenna, bo odpowiada na pytanie „skąd wziął się ten plik?”.

Bezpieczeństwo wymaga jednak jeszcze odpowiedzi na drugie pytanie: „co ten kod zrobi po uruchomieniu?”.

Zobacz również
CyberDefence24.pl - Digital EU Ambassador

Serwis CyberDefence24.pl otrzymał tytuł #DigitalEUAmbassador (Ambasadora polityki cyfrowej UE). Jeśli są sprawy, które Was nurtują; pytania, na które nie znacie odpowiedzi; tematy, o których trzeba napisać – zapraszamy do kontaktu. Piszcie do nas na: [email protected].

Reklama