Няма жадных нарадзенняў, незалежна ад колькасці коду: аўдыт 300 пакетаў MCP npm
Аўдыт архіву з тар-файламі 300 пакетаў сервера MCP на npm паказаў, што 217 з іх мелі код, які сканер ніколі не чытаў. Чаму для чыстага рэзультата неабходна дадаць паказанню павернення паверхні коду.
Трыццаць гэтых пакетаў npm з назвай, ў якой была частка MCP, было выкарана з рэестру і аналізавана як публікуемыя архівы у фармаце tarball, пры чым яны ніколі не былі інсталаваны і не запускаліся. Найболей значным рэзультатам не была колькасць віруснага програмнага забавы. Гэта была працяжка аналізу: у 217 з 300 пакетаў (72,3%) архів містыў код, які выконваліся пад час працы, але кожны такі файл знаходзіўся пад шляхам, які сканер намеравана ігнаруе, такім як dist/, build/ або мініфікаваны выходны файл. Апарат могаў прачытаць файлы manifest і README, запісаць спакойны рэзультат, але не аналізаваць ніякога з кода, які насправдзе мог бы выконвацца.
Разлік складаўся з 217 працяжак аналізу, 80 пакетаў з кодам, які падходзіў для аналізу, і 3 пакетаў, у якіх вовсе не было коду, які выконваліся пад час працы.
Гэта не значыць, што 72,3% пакетаў MCP ў цэлым застаюцца невіднымі для статычнага аналізу. Пакеты можна парсаваць, карты вываркі іноды вярна восстанавляюць первісны код, а спецыялізаваныя інструменты могу дэобфускуваць або аналізаваць створаны JavaScript. Аўтары доследжэння прыводзяць болей часткавы і корыстны вывад:
Негатывны статычны рэзультат не мае значэння, калі толькі не будзе указана колькісна велічына пераказвальнага коду была фактычна адзірвана.
Тут важны меркі. Рэзультат означае, што адны конкрэтны сканер не знайшоў нічога, што магло б быць прачытана ў 217 архівах тыпу tarball. Гэта не значыць, што гэтыя пакеты ўражаючыя або небезпечныя, чы ўсё-такі іншы аналізатор не мог ўсё працэса адзірваць.
Чаму MCP падымае рызыкі
Локальны ўраджэнны сервер MCP — гэта не проста бібліятэка, яку імпортуе програма. Праз звычны транспорт stdio кліент стварае яго як дзецячы працэс. Палітры безпекі праекту працэўна адзначаюць, што сервер мае тыя ж прывілеі на рэвэльні аптэкі, чым кліент, і што транспорт stdio SDK не забезпечвае сандбокса. Калі агент можа дасягнуць крэдытных даных, сетавага адрэса чыя локальнага інструмента, то сервер без сандбокса, верагодна, таксама зможа да яго дасягнуць.
Афіцыйныя рэкамендацыі па безпеке MCP прасуюць запускаць локальныя серверы з мінімальнымі прывілеямі і обмежваць доступ да файловай сістэмы і сеткі. Забезпечэнне такой ізоляцыі залежыць ад хоста чыя аператара. Перагляд коду застаецца важлівым, але застаецца вопыт, што можна часовісна сказаць пра файлы, якія на самай працэўнай інсталююць распрацоўшчыкі.
Як быў створаны прыклад
Гэта быў прыклад для зручнасці, а не перапіс пэўнай часткі экосыстэмы.
Колекціонер віконав 11 пошуків у рэестры npm, вікорыстовуючы такі фразі, як mcp server, model context protocol, mcp connector і modelcontextprotocol. На кожэн запіт отрымувалося до трох сторынок по 100 рэзультатыв; булі відалені дублікаты, залішаліся назві, што містылі mcp, і колькасць рэзультатыв обмежувалася 300. Рэйтынг пошуковіх рэзультатыв візначав, хто потрапляе до спіску — одын відавець міг з’явітыся кілька разів, а наявнісць mcp у назві не гарантувала, што гэта MCP server.
Для кожнага пакета була візначэна найновіша версія на момент збору даных, непасрэдна завантажувався архів рэестру, перэвіралася ціннісць інтэгрытэту, опублікована npm, а елементы пакета чыталіся в оператывній памяці. Усі 300 перэвірок інтэгрытэту пройшлі успішно, не вінікло жодніх помілок під час завантажэння чы апрацоўкі даных. Нічого не було встановлено, розпаковано у віконувальне серэдовішчэ чы запушчэно.
Сканер настроўваецца для высокай тачнасці. Ён шукае сеткавыя API, безпосерэдніх хостаў URL, вызывы падпроцэсаў, а таксама згадкі пра шляхі крэдытнаўых даных і вузкі набор фраз для атакі, пры чым ігнаруе тэстовы код, фіксаты, прыклады, папкі з скомпіляваным выходам, мініфікаўаныя файлы, карты выхаднага коду і ўсё, што мае размер больш 1 МБ. Такое ігнараванне зменшае колькасць непатрэбных даных, але таксама стварае конкрэтныя «слепыя пункты».
Рэзультаты
Інформацыя пра паверхностную пераглядку трэба паказваць разам з нараджанымі выводамі, а не ў прымечанні. Першая лінія рэзультатаў — галоўны вывод, а кожная наступная лінія павінна чытацца на адной з гэтых ліній. Напрыклад, наявнасць нуля згадак пра крэдытныя даны не значыць, што код ніколі не выкарыстоўвае такія даны; гэта значыць толькі, што сканер не знайшоў іх у кодзе, які ён вважаў патрэбным для аналізу, хоця 217 пакетаў не далі ягоў для перагляду.
Выдзеляюцца чатыры показнікі:
- Код, які выконваецца, але нуль прыдатных файлаў для выканання: 217 пакетаў.
- З гэтых 217 пакетаў 107 мелі карточку выхадных дадзенняў, а іншыя 110 — нямелі.
- Сігнал сеткавага API або literal-host у прыдатным кодзе: 50 пакетаў.
- Падзеі, супадзячыя з ін’екцыяй запыту: 2, і пасля ручнага аналізу оба былі адзначаны як хыбныя паўтарэнні.
Две хыбныя адзвячкі
Фразы у стыле ін’екцыі былі знайдзены ў двух пакетах, і пасля ручнага прачытання выявілася, што оба ўскладненні ўжо ў форме пояснюючага тэксту. У пакеце сервера дакументацыі Mastra версіі 1.2.22 былі прыклады ацэнкі з рэчамі на кшталт IGNORE PREVIOUS INSTRUCTIONS. У іншым пакеце сервера REMnux MCP версіі 0.1.71 паведамляеся, што прыклады віруснага програмнага забавы можу міткаваць рэчы, схожыя на ін’екцыю запыту, і прадаўаеся, як аналізаваць іх.
Не было таксама падзеку пра спробу маніпулявацыі агентам. Гэта вядомая слабас сканавання ключоўых слов: дакументацыя па безпецы, прылады для тэставання і ворагоўскія інструкцыі можу мець ідэнтычныя строкі, і толькі кантэкст памагае з’ясавіць, калі які з іх.
Зловучы пакет для тэставання, які павёў нуль
Одны пакет выканаў ролю для кантролю паверхні пакрыцча. malicious-mcp-server 1.5.0 опісвае сябе як намерна зловучы сервер MCP для тэставання з канца ў канец. Яго архіў tarball меў тры файлы: package.json размахам 970 байт, README.md — 742 байт, а dist/index.js — 610,358 байт.
Пад час першага сканавання былі прачытаны два маленькіх тэкстовых файлы, быў прыгнуцаны dist/index.js, не было знайдзена ніякіх сігналав паведання, і пакету быў прызначаны рызыковы бал 0. Пасля чаго падрахунак чыстых токэнаў у прыгнутым бандле паказаў exec шасць разоў, eval( два разы, base64 52 разы і raw.githubusercontent.com тры разы.
Такім чынам, адказчык не быў позытывным: не удалося з’ясаваць рэальны стан працы праграмы. Згідна дэйнавучым правілам, не можна было выявіць ступень пакрыцтва часу експлуатацыі. Этыя стрынгі самі по сабе не падтверджуюць ні ўработкі, ні злыя намеры, а маніфест пакета дае нехватную інформацыю. Справа ў тым, што пакет, які несе весь рызык, так і не дасягнуў этапы, якая б выдала значэнне нуля.
Тэхніка не была прычыной
Выключэнне створанага выходу — гэта рашэнне з боку дызайнера, а не правіло галузі. Іншы сканер можа аналізаваць JavaScript у пакеце, пераглядаць дрэво сынтаксісу, распаковываць модулі, выкарыстоўваць карты выхаднага коду, аналізаваць метаданы залежнасцяў, поручваць джэрэла коду або працаваць з правіламі, напісанымі для мініфікацыі коду. Кожны з эых методаў жэртвуе часткай шыроцы і точнасці, каб расшырыць дыямэт аналізу.
Памылка крыўцяе ў тым, што жаданых нараджэння не спрыймаюць як адна ўмова, адкуль можа выйсці прынеймна трохі разных сітуацый:
- Быў прачытан адпаведны код, і жадных правіла не было актывацыя.
- Быў прачытан адпаведны код, але правіла не змоглі распазнаць яго працэс.
- Адпаведны код так і не быў прачытан.
Толькі першы варыянт ёсць значымым, чыстым рэзультатам, але нават гэта не ўсуняе падазроў у безпеку.
Што павінен адкрываць хорашы звяты
Сканер не павінен з’едынаць рэзультат «нічога не знайдзена» і «нічаго не было пераканалена» ў адны зелены рэзультат. Для файлаў пакета кожнаму падсумку выявленых проблем павінна супакоўвацца адпаведная квітанцыя пра пакрыцце:
- Скількі існуе файлаў пад час выканання, скількі з іх было аналізавана і скількі байтов гэта пакрыло.
- Усе, што было адключана, класіфікавана па прычынах: створаныя шляхі, ліміты розмеру, непадтрымваныя фарматы, адказы пра парсаванне.
- Нявісць картоў выхаднага коду і чы можна было вярнуць сабе рэальны выхадны код з іх.
- Калі саме набор правіла і версія сканера стварылі гэты рэзультат.
Гэта невялікая змена ў фармаце адчытнай інфармаціі, якая дае вялікую выгоду з точкі зору довер'я, адтаке ўчаснікі перагляду можаць з'ясавіць, чы рэзультат без паўтароўкі ёсць доказам, чы толькі праблемай з візуабельнасцю.
Чаму поведзенне часу выканання все ўсё мае значэнне
Статычныя перагляды — гэта толькі момантальны знімак. Працэздатнасць можа змяніцца пасля апдэйта, і команда на кшталт npx package-name можа запускаты новы код, хоць локальная настройка MCP застаецца той самай. Таму кантролі пад час выканання допамагаюць статычным пераглядам, а не конкуруюць з ямі. Кожны локальны сервер павінен працаваць пад сябеіндэксам з політыкай мінімальных прав. Яго фактычныя направлення і можлівасці павінны быць задокументаваны, а базовы стан якраз затверджаны. Пасля чаго наступныя запускі паўставляюцца у співставленні з сабеіндэксам таго сервера, такім чынам вядома стане змяна ідэнтычнасці пасля змены настройкі, а таксама тое, чыгульнае застаецца пакета пасля апдэйта, які выкарыстоўваецца за незменныяя ваказанні, калі змянююцыся можлівасці пад час выканання.
Адзін з інструментаў на ачытым кодзе следуе гэтаму модэлю, выканаючы кожны сервер MCP як самостойную ентытнась, напрыклад mcp:github, з адзінаковай політыкай, падпісаным базавым станам і запісам абяцэнняў. Ён прызначаны як рэзервны механізм пад час выканання для перагляду кода, а не як замена. Падтрымка платформы неравнамерная: у macOS Seatbelt прыкрэпляе выходныя сокеты да loopback-праксі, тады як у Linux bubblewrap нараз чыніць можлівым обмежэнне файловай сістэмы і працэсаў, а таксама наявнась зменных сераўніка, без адпаведнага жорсткаг прыкрэплення да сеткі.
Новейшыя даследжэння развіваюцца па той жа направленні. TrustShiftProbe, прэпрынт з лістапада 2026 года, мадэлюе серверы MCP, якія дзейнуюць нормальна і пазней зміняюць сваё поведзенне на адзынаковай горызонталі довер'я, і таму тэстуе захоны пад час выканання, заснованыя на базавых параметрах поведзення. Прэпрынт не ўтварае кансенсусу, але яго модэль аб'яцэнняў, урахоўваючы час, ёсць правільной, адтолькі як довер'е можа зменшыцца пасля завершэння перагляду.
Меры аўдыту
- Выбір быў здзейснены на аднойчыне рангавання пашуковых вынікоў і фільтрацыі па назве, таму прыклад не ўзяты ані вэлкантна, ані як рэпрэзентатыўны.
- Усі паказаныя цыфры стосуюцца 1 верасня 2026 года, і як содэржанне npm, так і вынікі пашуку змінююцца.
- Мераваліся тарбаллы, а не тое, чыi кожны з іх ўжо працюе як сервер MCP.
- Фраза «scanner blind» стосуецца правіл адклэювання гэтага сканера, а не статычнай аналізу в цэлым.
- Была здабыта статыстыка па карточкам выхідных кодаў, але ніхто не пераканаліся, чыi кожная з іх містыць корыстны выхідны код.
- Буквальныя URL-адрэсы і назвы API ўжо ёсць статычнымі падказкамі і не паказваюць, чыi кодавы шлях працюе.
- Пакеты ніколі не былі запусцаны, таму месца падачы даных у час працы застаюцься невядомымі.
- Тое, што нічога не было знайдзена, не ёсць вердыктом пра безпеку.
Павтарэнне запуску
Ёсць кантрольны файл з зафіксаванымі вынікамі, які можна вікорыстаць як вхідны даныя для стварэння точна таго ж набора тарбаллоў:
# 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
Ёсць можласць заўважыць свежы фотакадру з 300 пакетамі з ныякіх рэзультатаў пошуку 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
Ніякі з эўтых спосабаў не інсталюець пакет і не выкананае яго код; оба толькі завантажуюць і чытаюць архівы у фармаце tarball.
Короткі чэрніцк для корыстувачаў MCP
- Закрэпіце версіі. Точная версія плюс значэнне целаснасці лепшыя, чым вызов npx без указвання версіі.
- Паглядзіце на публікуемы артыфакт. Чысты рэпазітарый малая значэнне, калі інсталаваны архів tarball мае створаны пакет, які ніхто не ачыніў.
- Запытайце па показніках кавэражу. Якшо у звятыні немае падходзячых файлаў часу выканання, спрыймайце гэта як недоступнасць, а не як чыстасцю.
- Ізоліруйце кожны сервер аднародна, заставіўшы яму сабеідэнтнасць, дыяпазон файлавой сістэмы і дазволеныя хосты, незалежна ад таго, чы рухаецца ён локальна чы праз мост.
- Зробіце доверлівасць цялявым крокам: запісайце вядомы правільны выкананне, падпісайце гэты базовы стан і заблокуйце CI чы заставіце перагляд, калі змянююцца можлівасці.
Адзінаковасць не ў тым, каб прыпыніць статычны аналіз, а ў тым, каб паказаць ступень яго адкрытасці. Для сервераў MCP і падобных інструментаў, якія вікорыстоўваюць агенты, чытанне коду, аналіз створаных вырабаў, пераконтраванне паводжэння коду, працяванне ў сандбоксе, фіксаванне поведзення пад час выканання і выяўленне адхылэнняў — усе гэта пакрывае разныя аспекты адной проблемы. Найбольшаю паляканняй у адзорнай даповедзі можа быць не выяўленне віруснага програмнага забавы, а ўсё ж нуль нараджэнняў, што заставляе задаць наступны пытанне: нуль нараджэнняў для якога ж обсягу коду?