Хакери тихомълком са внедрили зловреден код в 42 реални GitHub хранилища. Капаните се задействат, когато разработчик отвори проект с Claude, Gemini, Cursor или VS Code. Хранилищата принадлежат на 11 легитимни собственици, сред които индивидуални разработчици, студенти и една компания.

Скритият код се намира във файл с име .github/init.js и е огромен – между 12,9 MB и 13,7 MB. Малки конфигурационни файлове за всеки инструмент извикват този скрипт при начало на сесия или при отваряне на папка.

Разработчиците вече се опасяват от инжектиране на команди (prompt injection) чрез GitHub коментари, които подвеждат AI агентите, но този случай не изисква хитър prompt. Той просто злоупотребява със стартовите куки (hooks), на които инструментите се доверяват.

Изследователи от JFrog Security Research откриха въоръжените хранилища, докато проучваха npm червей, който следят като кампанията „testmetest“.

Друга компания, SafeDep, пръв път описа npm частта на 22 октомври и не съобщи за потвърдени жертви. Анализът на JFrog върху GitHub частта показа, че реални хранилища вече са били въоръжени.

Хакери превземат 42 GitHub хранилища

Зловредният код е преработена версия на скрит CI издател на име ci.js. CI издателят е скрипт, който се изпълнява в GitHub Actions и публикува нови пакети в npm.

JFrog посочват, че операторът е искал да превърне откраднатия достъп до GitHub и npm в нови злонамерени версии на пакети, които от своя страна връщат още откраднат достъп в цикъла. Същата supply chain кампания TrapDoor е била насочена и срещу AI асистенти за програмиране, така че този трик не е напълно нов.

Във всяко засегнато хранилище файловете с куки изчакват задействане. Например файлът с настройки на Claude изпълнява node .github/init.js || bun .github/init.js при начало на сесия.

Съответни тригери са поставени за Gemini, за MCP конфигурацията на Cursor и за задачите на VS Code при отваряне на папка. Някои проекти имат и промени в package.json, composer.json или Makefile. Казано просто, обичайно действие като отварянето на работно пространство може да стартира зловредния код.

Файловете остават скрити заради размера си. Търсенето на код в GitHub не индексира огромните обекти, а contents API не може да ги върне.

Верига на атаката (източник – JFrog)
Верига на атаката (източник – JFrog)

Първото сканиране на JFrog откри 26 хранилища, а файловете изглеждаха празни. Директната проверка на дърветата на хранилищата повиши общия брой до 42. Находките са отразени и от The Register.

И десетте варианта на обвивката се декодират до един и същи зловреден код, така че разликите в размера не променят действието му. Атакуващият е фалшифицирал и историята: на 28 септември скриптови пакети от комити са копирали стари съобщения и дати от реалната история и са добавили skip-checks:true. Така активността е изглеждала много по-стара, отколкото е в действителност.

Откраднати акаунти, native добавки и връзки с cPanel

JFrog проследява няколко отвлечени идентичности. Един от акаунтите, leamasuero, принадлежи на разработчик с реална история на работа от 2014 до 2022 г.

До юли 2026 г. той е използван за тестове, а на 28 септември атакуващият преименува хранилища и въоръжава 13 от тях за две минути. В акаунта на компанията Crayon-Biz-LLP комитите идват от поне двама членове, което навежда на мисълта за няколко откраднати идентификационни данни.

Тактиката е променена и от страна на npm. Три пакета съдържат компилирана native добавка и криптиран файл на име .napi_cache. Добавката го декриптира с XOR ключ 0x96, записва скрипт във временна папка и го стартира във фонов режим.

Тя остава неактивна на CI системи, в контейнери, малки виртуални машини и при дебъгери, затова автоматизираните скенери я пропускат. Windows версията проверява и за инструменти като Wireshark, Fiddler и x64dbg. Това е същият вид привидно надеждна стръв, виждана в кампанията с фалшиви AI инструменти, насочена към разработчици.

JFrog откриват и работни потоци за сканиране в същите отвлечени акаунти. Те изтеглят инструмент в /tmp/.svc и сканират за cPanel и WHM системи, уязвими към CVE-2026-41940 – заобикаляне на автентикацията.

JFrog не откриват доказателства, че някой cPanel сървър действително е компрометиран. Връзката е оперативна, а не една доказана верига от всяка npm инфекция до експлойта.

Защитниците трябва да премахнат злонамерените версии на пакетите и да изградят наново засегнатите системи от доверени източници. Те трябва да сменят идентификационните данни за GitHub, npm, облачни услуги, SSH и AI доставчици и да проверят всяко достъпно хранилище за описаните по-горе файлове с куки.

Екипите трябва да четат дърветата на хранилищата директно, вместо да разчитат на търсене. Те трябва да следят и за HalluSquatting, което отравя AI асистентите, тъй като AI инструментите могат да бъдат насочени към фалшиви ресурси.

Редът има значение: премахнете устойчивостта (persistence) на net-health-checker и pkg-runtime, преди да отмените откраднатия GitHub токен, защото червеят съдържа изтриващ механизъм (wiper), който се задейства при отмяна на токена.

Индикатори за компрометиране (IoCs):

ТипИндикатор
C2 на скенера43[.]228[.]157[.]68:80
Шаблон за изтегляне на скенераhxxp[:]//43[.]228[.]157[.]68:80/api/dl/<amd64\|386\|arm\|arm64>
Точка за експортиране на данниhxxps[:]//aiarmor[.]website/v1/api
Изтегляне на loader за native добавкатаhxxps[:]//raw[.]githubusercontent[.]com/CementBeetleSteeple/node-cache-utils/main/loader.js
GitHub акаунт на оператораCementBeetleSteeple
Маркер на кампаниятаmsync-3f7a
Префикс на комит за dead-drop на токениAutoSyncComplete:
Съобщение на комит / trailerchore: sync; skip-checks:true
Маркер на инфекциозен комитshellpanel execution smoke
Шаблони на клоновеchore/ci-<hex>; deps/upd-<digits>
Шаблон на файл за експортиране на данниdata/snap-<timestamp>-<n>.json
Злонамерени npm пакетиdata-pipeline-testmetest, event-bus-lite-testmetest, event-emitter-testmetest, log-rotate-testmetest, log-sink-testmetest, net-codec-testmetest, npm-publish-testmetest, pixel-map-testmetest, retry-utils-testmetest, test-brotli-testmetest, test-brotli2-testmetest, @iobandamwer/cache-helper, @iobandamwer/native-helper, path-stream-utils-testmetest
SHA-256, зловреден код на издателя при жертвите _p9d83919bfdb0e14018f1a6f2b8b6586de59b60dfdcfbdb5ae1a1556c23cc4793
SHA-256, Bun bootstrap при жертвите _b3dc40fc55302664c07c9d9182ffd95910aeb366fcd417fbdad0a90cdeb8ea69e
SHA-256, зловреден код на издателя ci.js8506042b383ab46545c27a402eb2dc973696a93af71181b175b1d87972843a43
SHA-256, зловреден код на издателя ci.js v3783a4ac906cc9b2eaf5cd13408ea95db6ce52a46d9af11aad1a5b167af69589f
SHA-256, loader на stable-scripts-9965a516dd7867af83f8be0cc3e926fdfd964097f0e7665596b05fe5234be7e2b5e9
SHA-256, декодиран етап на stable-scripts-9965ccfd769acc024edc409ef879198d2a2398beee60930f2b3f2771ded1e14e0c57
SHA-256, зловреден код на издателя на stable-scripts-99657ad216b3afd2f40a147c80733c7309fb3d3a7f52ee78149c8e51672cfb617d07
SHA-256, Shellpanel mocke3cb383615fc70bce9b5bcd1c7a394132b50483daaf231a04ee90d4690962c73
SHA-256, маркиращ инструмент Shellpanel17614e98b613b17d0e1bb7125ab203715dd397661b897d8d18dbb77864c1839f
Файлове и пътища.github/init.js, /tmp/.svc, addon.node, addon_win.node, .napi_cache (XOR ключ 0x96), /tmp/.<pid>, /tmp/.hc, %TEMP%\.nc<PID>.js, фалшив CodeQL артефакт scan-output
Устойчивост (persistence)net-health-checker, pkg-runtime, ~/.local/bin/net-health-checker.sh, ~/.config/net-health-checker/, ~/.local/share/runtimes/sync.py, /var/tmp/.fontconfig_state
Куки за AI и IDE.claude/settings.json, .gemini/settings.json, .cursor/mcp.json, .cursor/rules/setup.mdc, .vscode/tasks.json

Забележка: IP адресите и домейните са умишлено дефанг-нати (напр. [.]), за да се предотврати случайно разрешаване или превръщане в хипервръзки. Връщайте оригиналния вид само в контролирани платформи за threat intelligence като MISP, VirusTotal или вашия SIEM.