Strona główna / Artykuły

Brak wyników w zależności od ilości kodu? Audyt 300 pakietów MCP npm

Audyt pliku tarball zawierającego 300 pakietów serwera MCP na npm wykazał 217 pakietów, w których kod uruchamiany nie został nigdy przeczytany przez skaner. Dlatego czysty wynik wymaga dołączenia potwierdzenia zakresu testowania.

Wydawca: REACTAPP.TOP8 min czytania1871 słów

Źródła: I Audited 300 MCP-Related npm Packages. My Scanner Couldn’t Inspect Runtime Code in 217. So I created Driftward.

Trzysta pakietów npm o nazwie zawierającej MCP zostało pobrańo z rejestru i przeanalizowanych jako opublikowane pliki tarball, bez ich instalowania ani uruchamiania. Najbardziej uderzającym wynikiem nie była liczba oprogramowania złośliwego. Chodziło o błąd w zakresie analizy: w 217 z 300 pakietów (72,3%) plik tarball zawierał kod uruchamiany w czasie rzeczywistym, jednak każdy taki plik znajdował się w ścieżce, którą skaner celowo pomija, takiej jak dist/, build/ lub pliki po minifikacji. Narzędzie potrafiło odczytać plik manifest oraz README, poinformować o pozytywnym wyniku i nie przeanalizować żadnego z kodów, które faktycznie miałyby zostać wykonywane.

Rozkład wyników był następujący: 217 braków w analizie, 80 pakietów z kodem uruchamianym w czasie rzeczywistym oraz 3 przypadki, gdy w ogóle nie znaleziono takiego kodu.

To nie oznacza, że 72,3% pakietów MCP jest ogólnie niewidocznych dla analizy statycznej. Pakiety te można analizować, mapy źródłowe czasami przywracają oryginalny kod, a specjalistyczne narzędzia mogą deobfuskować lub zrozumieć generowany JavaScript. Stwierdzenie to jest bardziej precyzyjne i przydatne:

Ujemny wynik analizy statycznej nie ma żadnego znaczenia, chyba że określa również, ile kodu wykonywalnego faktycznie zostało sprawdzone.

Tutaj ma znaczenie zakres analizy. Wynik oznacza, że jeden konkretny skaner nie znalazł nic, co nadawałoby się do odczytania w 217 plikach typu tarball. Nie sugeruje to, że te pakiety są złośliwe lub niebezpieczne, ani że inny analizator nie mógłby ich sprawdzić.

Dlaczego MCP zwiększa stopień ryzyka

Localny serwer MCP to nie tylko biblioteka, którą importuje aplikacja. Przez standardowy transport stdio klient uruchamia go jako proces potomny. Polityka bezpieczeństwa projektu stanowi, że serwer posiada te same uprawnienia na poziomie środowiska co klient, a transport stdio w SDK nie oferuje żadnej izolacji. Jeśli agent może uzyskać dostęp do danych uwierzytelniających, adresu sieciowego lub lokalnego narzędzia, serwer bez izolacji prawdopodobnie również będzie mógł do nich dotrzeć.

Oficjalne wytyczne dotyczące bezpieczeństwa MCP zalecają uruchamianie lokalnych serwerów z minimalnymi uprawnieniami oraz ograniczanie dostępu do systemu plików i sieci. Zapewnienie takiej izolacji zależy od hosta lub operatora. Przegląd źródeł pozostaje ważny, ale otwartym pytaniem jest to, co można uczciwie powiedzieć o plikach, które faktycznie instalują deweloperzy.

Sposób utworzenia przykładu

Był to przykład służący wygodzie, a nie przegląd całego ekosystemu.

Kolektor przeprowadził 11 wyszukiwań w rejestrze npm, używając fraz takich jak mcp server, model context protocol, mcp connector oraz modelcontextprotocol. Każde zapytanie przynosiło do trzech stron wyników po 100 sztuk, usuwano duplikaty, zachowywano nazwy zawierające „mcp”, a liczba wyników ograniczono do 300. Kryteria sortowania wpływają na to, które elementy trafiają do wyników – jeden wydawca może pojawić się wiele razy, a nazwa zawierająca „mcp” nie gwarantuje obecności serwera MCP.

Dla każdego pakietu ustalono najnowszą wersję w momencie zbierania danych, bezpośrednio pobrał się plik tarball z rejestru, sprawdzono wartość integralności podaną przez npm, a elementy pakietu zapisano w pamięci. Wszystkie 300 sprawdzeń integralności przeszło pomyślnie, nie wystąpiły żadne błędy przy pobieraniu ani analizie. Nic nie zostało zainstalowane, rozpakowane w środowisko wykonywalne ani uruchomione.

Skanner jest dostrojony pod kątem precyzji. Szuka API sieciowych, dosłownych hostów URL, wywołań podprocesów, wzmianek o ścieżkach danych uwierzytelniających oraz wąskiego zestawu fraz służących do iniekcji, pomijając przy tym kod testowy, pliki pomocnicze, przykłady, foldery z wynikami kompilacji, pliki minifikowane, mapy źródłowe oraz wszystko, co przekracza 1 MB. Takie pominięcia zmniejszają ilość niepotrzebnych informacji, ale jednocześnie tworzą mierzalne „ślepe punkty”.

Jakie były wyniki

Informacje o zakresie badania powinny znajdować się obok ustaleń, a nie w przypisie. Pierwszy wiersz wyników przedstawia główne ustalenie, a każdy kolejny wiersz musi być analizowany w kontekście tego pierwszego. Na przykład brak jakichkolwiek odniesień do danych uwierzytelniających nie oznacza, że w analizowanym materiale w ogóle nie ma takich danych. Oznacza to jedynie, że skanner nie znalazł ich w kodzie uznanym za odpowiedni do analizy, mimo że 217 pakietów nie dostarczyło mu żadnego kodu nadającego się do przetworzenia.

Wyróżniają się cztery kluczowe wskaźniki:

  • Kod w czasie wykonywania, ale brak odpowiednich plików: 217 pakietów.
  • Z tych 217 pakietów 107 zawierało mapę źródeł, a pozostałe 110 nie.
  • API sieciowe lub sygnał literal-host w odpowiednim kodzie: 50 pakietów.
  • Zgodności typu prompt-injection: 2, a przegląd ręczny potwierdził, że obie były fałszywymi alarmami.

Dwa fałszywe alarmy

W dwóch pakietach znaleziono frazy typu injection, a po ręcznej analizie okazało się, że obie to teksty wyjaśniające. Jeden z nich, serwer dokumentacji Mastra w wersji 1.2.22, zawierał przykłady wykorzystania z ciągami tekstowymi takimi jak IGNORE PREVIOUS INSTRUCTIONS. Drugi, serwer REMnux MCP w wersji 0.1.71, ostrzega przed tym, że przykłady malware mogą zawierać ciągi typu prompt-injection, i podaje analitykom instrukcje dotyczące ich postępowania.

Nie znaleziono również dowodów na próbę manipulacji agentem. Jest to znana słabość skanowania kluczowych słów: dokumentacja bezpieczeństwa, pliki testowe oraz szkodliwe instrukcje mogą zawierać identyczne ciągi znaków, a tylko kontekst pozwala określić, który z nich jest który.

Złośliwy pakiet testowy, który otrzymał wynik zero

Jeden z pakietów służył do kontroli zakresu testowania. malicious-mcp-server 1.5.0 opisuje siebie jako celowo złośliwy serwer MCP do testowania end-to-end. Jego plik tarball zawierał trzy pliki: package.json o wielkości 970 bajtów, README.md o wielkości 742 bajty oraz dist/index.js o wielkości 610 358 bajtów.

Skanowanie pierwszej fazy przeczytało dwa małe pliki tekstowe, pominęło dist/index.js, nie znalazło żadnych sygnałów behawioralnych i przyznało pakietowi wynik ryzyka 0. Późniejsze liczenie surowych tokenów w pominiętym pliku pokazało sześć wystąpień funkcji exec, dwa wystąpienia eval(), 52 wystąpienia funkcji base64 oraz trzy wystąpienia adresu raw.githubusercontent.com.

Zatem uczciwa ocena nie była pozytywna – nie udało się ustalić pełnego zakresu działania w ramach obowiązujących zasad. Te ciągi znaków same w sobie nie dowodzą ani wykonywania kodu, ani złośliwości, a manifest pakietu dostarcza brakującego kontekstu. Chodzi o to, że pakiet niosący całe ryzyko nigdy nie przeszedł testu, który miał wydać wynik zero.

Technika nie była winna

Pominięcie wygenerowanego wyniku to decyzja projektowa, a nie zasada danej dyscypliny. Inny skaner mógłby analizować JavaScript w pakiecie, sprawdzać drzewo składniowe, rozpakowywać moduły, wyodrębniać mapy źródłowe, śledzić metadane zależności, porównywać pochodzenie kodu lub stosować reguły napisane dla skompresowanego kodu. Każda z tych metod poświęca część szybkości i dokładności, aby uzyskać szerszy zakres sprawdzania.

Błąd polega na traktowaniu braku znalezisk jako jednej warunku, ponieważ może on oznaczać co najmniej trzy różne sytuacje:

  1. Odczytano odpowiedni kod i żadna z reguł nie została aktywowana.
  2. Odczytano odpowiedni kod, ale reguły nie były w stanie rozpoznać jego zachowania.
  3. Odpowiedni kod w ogóle nie został odczytany.

Tylko pierwszy wynik jest sensownym, czystym rezultatem, a nawet on nie jest dowodem na bezpieczeństwo.

Czego powinien zawierać dobry raport

Skaner nie powinien łączyć informacji o braku dopasowań i braku przeprowadzonej inspekcji w jeden zielony wynik. W przypadku artefaktów pakietu, do każdego podsumowania ustaleń powinien dołączać się dowód pokrycia:

  • Ile istnieje plików w czasie wykonywania, ile z nich zostało przeanalizowanych oraz ile bajtów to obejmuje.
  • Wszystko, co zostało wykluczone, podzielone według przyczyny: utworzone ścieżki, limity wielkości, nieobsługiwane formaty, błędy parsowania.
  • Obecność map źródłowych oraz to, czy można z nich odzyskać rzeczywiste źródła kodu.
  • Która zbiórka reguł i wersja skanera dały ten wynik.
  • Odrębny stan wyniku w przypadku braku znalezisk w sprawdzanym kodzie w porównaniu z niedostępną informacją o pokryciu podczas wykonywania.
  • Jest to niewielka zmiana w sposobie raportowania, która przynosi duży wzrost zaufania, ponieważ recenzenci mogą stwierdzić, czy spokojny wynik jest dowodem, czy jedynie brakiem widoczności.

    Dlaczego zachowanie podczas wykonywania nadal ma znaczenie

    Przegląd statyczny to jedynie chwilowy obraz sytuacji. Zachowanie może ulec zmianie po aktualizacji, a polecenie takie jak npx package-name może odwoływać się do nowego kodu, mimo że lokalna konfiguracja MCP pozostaje niezmieniona. Dlatego też mechanizmy kontrolne w czasie wykonywania aplikacji uzupełniają pracę statyczną, zamiast z nią konkurować. Każdy lokalny serwer powinien działać pod własną tożsamością, stosując zasadę minimalnych uprawnień. Jego rzeczywiste destynacje i możliwości powinny być rejestrowane, a podstawa porównawcza musi zostać wyraźnie zatwierdzona. Późniejsze uruchomienia są następnie porównywane z historią tego serwera, dzięki czemu zmiana konfiguracji powoduje odchylenie tożsamości, a aktualizacja pakietu przy niezmienionej definicji pozostaje widoczna, jeśli zmieniają się możliwości serwera w czasie wykonywania aplikacji.

    Jedno narzędzie open-source stosuje ten model, otaczając każdy serwer MCP jako odrębnego podmiotu, na przykład mcp:github, z oddzielną polityką, podpisanym punktem odniesienia oraz rejestracją odchyleń. Służy ono jako zapora awaryjna w czasie działania systemu do przeglądania kodu źródłowego, a nie jako jego zamiennik. Wsparcie platformowe jest nierówne: na macOS Seatbelt przypina ruch wyjściowy do proxy typu loopback, natomiast na Linux bubblewrap zapewnia dotychczas ograniczenia plików systemowych i procesów oraz zmienne środowiskowe proxy, bez odpowiedniego sztywnego przypięcia do sieci.

    Nowsze badania podążają tą samą linią. TrustShiftProbe, preprint z sierpnia 2026 roku, modeluje serwery MCP, które działają normalnie, a następnie zmieniają swoje zachowanie w określonym momencie, i testuje mechanizmy obronne działające w czasie rzeczywistym oparte na punktach odniesienia behawioralnych. Preprint nie stanowi konsensusu, jednak jego model zagrożeń uwzględniający czas jest właściwy, ponieważ zaufanie może się zmniejszyć po zakończeniu przeglądu.

    Ograniczenia audytu

    • Wybór został dokonany na podstawie rankingu wyszukiwania i filtrowania nazw, więc próbka nie jest ani losowa, ani reprezentatywna.
    • Wszystkie dane dotyczą 1 września 2026 roku, a zarówno zawartość npm, jak i wyniki wyszukiwania ulegają zmianie.
    • Mierzono pliki tarball, a nie to, czy każdy z nich stanowi działający serwer MCP.
    • Wyrażenie „scanner blind” odnosi się do reguł wykluczania tego skanera, a nie do analizy statycznej jako całości.
    • Liczono mapy źródłowe, jednak nikt nie sprawdził, czy każda z nich zawiera użyteczne kod źródłowy.
    • Dosłowne adresy URL i nazwy API to statyczne wskazówki i nie pokazują, że dany ścieżka kodu jest uruchamiana.
    • Pakietów nigdy nie uruchamiano, więc cele sieciowe w czasie wykonywania pozostają nieznane.
    • Brak znalezisk nie jest werdyktem dotyczącym bezpieczeństwa.

    Odtworzenie procesu

    Aby odtworzyć dokładny zestaw plików tarball, użyj zamrożonego pliku z wynikami jako danych wejściowych:

    # self-bootstrapping — no install needed
    git clone https://github.com/abdalhafeezbushara/driftward.git
    cd driftward
    python3 research/mcp-npm-audit-2026-09-01/audit.py \
      research/mcp-npm-audit-2026-09-01/results.json \
      /tmp/mcp-audit-rerun.json
    

    Aby pobrać aktualny zrzut stanu 300 pakietów z bieżących wyników wyszukiwania w npm:

    N=300 ./detonate/fetch-corpus.sh /tmp/mcp-packages.txt
    python3 research/mcp-npm-audit-2026-09-01/audit.py \
      /tmp/mcp-packages.txt /tmp/mcp-audit-current.json
    

    Ani jedna z tych ścieżek nie instaluje pakietu ani nie wykonywaje jego kodu; obie jedynie pobierają i czytają pliki tarball.

    Krótki wykaz sprawdzania dla użytkowników MCP

    • Zabezpiecz wersje. Dokładna wersja wraz z wartością integralności jest lepsza niż wywołanie npx bez określenia wersji.
    • Przyjrzyj się opublikowanemu artefaktowi. Czysty repozytorium ma niewielkie znaczenie, jeśli zainstalowany plik tarball zawiera utworzony zestaw plików, którego nikt nie otworzył.
    • Zapytaj o dane dotyczące zakresu pokrycia. Jeśli raport nie wykazuje żadnych odpowiednich plików w czasie działania, traktuj to jako brak dostępności, a nie jako czystość.
    • Izoluj każdy serwer osobno, nadając mu własną tożsamość, zakres systemu plików oraz dozwolone hosty, niezależnie od tego, czy działa lokalnie, czy przez most.
    • Uczynij zaufanie świadomym krokiem: zapisz udaną sesję działania, podpisz tę bazę i zablokuj proces CI lub zażądaj przeglądu po zmianie możliwości.

    Rezygnacja z analizy statycznej nie jest kluczowym wnioskiem; istotne jest podanie jej zakresu. Dla serwerów MCP oraz podobnych narzędzi używanych przez agenty, czytanie kodu źródłowego, analiza utworzonych artefaktów, sprawdzanie pochodzenia danych, działanie w środowisku izolowanym, rejestrowanie zachowania podczas wykonywania oraz wykrywanie odchyleń obejmują różne aspekty tego samego problemu. Najbardziej przerażającym ustępem w raporcie bezpieczeństwa może nie być informacja o wykryciu złośliwego oprogramowania, lecz brak żadnych ustaleń, co rodzi kolejne pytanie: brak ustaleń w odniesieniu do jakiej części kodu?