Хакери тихомълком са внедрили зловреден код в 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 откри 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: |
| Съобщение на комит / trailer | chore: 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, зловреден код на издателя при жертвите _p | 9d83919bfdb0e14018f1a6f2b8b6586de59b60dfdcfbdb5ae1a1556c23cc4793 |
| SHA-256, Bun bootstrap при жертвите _b | 3dc40fc55302664c07c9d9182ffd95910aeb366fcd417fbdad0a90cdeb8ea69e |
| SHA-256, зловреден код на издателя ci.js | 8506042b383ab46545c27a402eb2dc973696a93af71181b175b1d87972843a43 |
| SHA-256, зловреден код на издателя ci.js v3 | 783a4ac906cc9b2eaf5cd13408ea95db6ce52a46d9af11aad1a5b167af69589f |
| SHA-256, loader на stable-scripts-9965 | a516dd7867af83f8be0cc3e926fdfd964097f0e7665596b05fe5234be7e2b5e9 |
| SHA-256, декодиран етап на stable-scripts-9965 | ccfd769acc024edc409ef879198d2a2398beee60930f2b3f2771ded1e14e0c57 |
| SHA-256, зловреден код на издателя на stable-scripts-9965 | 7ad216b3afd2f40a147c80733c7309fb3d3a7f52ee78149c8e51672cfb617d07 |
| SHA-256, Shellpanel mock | e3cb383615fc70bce9b5bcd1c7a394132b50483daaf231a04ee90d4690962c73 |
| SHA-256, маркиращ инструмент Shellpanel | 17614e98b613b17d0e1bb7125ab203715dd397661b897d8d18dbb77864c1839f |
| Файлове и пътища | .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.