14 июля 2026 года подразделение Microsoft Threat Intelligence зафиксировало скоординированную атаку на цепочку поставок, направленную на организацию @asyncapi в реестре npm. Эта организация поддерживает набор пакетов для спецификации AsyncAPI и генерации кода. В течение примерно полутора часов были переизданы пять версий четырёх пакетов, каждая из которых содержала одинаковую вредоносную инъекцию: @asyncapi/specs (в предрелизе 6.11.2-alpha.1 и стабильном релизе 6.11.2), @asyncapi/generator версии 3.3.1, @asyncapi/generator-components версии 0.7.1 и @asyncapi/generator-helpers версии 1.1.1.
Описание
Особенность атаки заключается в том, что @asyncapi/specs является транзитивной зависимостью множества инструментов AsyncAPI. Это означает, что под удар попали рабочие станции разработчиков, конвейеры CI/CD, сборки контейнеров и производственные среды, которые разрешили и импортировали скомпрометированные версии в течение времени воздействия. В отличие от более распространённого шаблона атак на цепочку поставок, использующего postinstall-хуки, данная кампания срабатывает в момент загрузки модуля (при выполнении операторов require или import). Компрометирующий код выполняется сразу при импорте любым приложением или сборочным процессом. Поскольку триггером является именно импорт, а не скрипт установки, стандартная команда npm install -ignore-scripts не предотвращает заражение.
Вторая стадия дешифрует и исполняет Miasma - модульную среду, которая включает активный командно-контрольный сервер (C2), механизмы закрепления в системе и децентрализованные резервные каналы связи. Сбор учётных данных, распространение и другие опасные модули были отключены в данной сборке, однако могли быть активированы через механизмы закрепления.
Согласно анализу Microsoft Threat Intelligence, атака началась с вредоносного pull-request’а против репозитория asyncapi/generator. Злоумышленник использовал неправильно настроенный workflow (путь выполнения действий) GitHub Actions под названием pull_request_target. Этот workflow выполнял непроверенный код из pull-request’а и раскрыл персональный токен доступа (PAT) бота asyncapi-bot. Получив токен, атакующий смог создавать несанкционированные коммиты в ветки, помеченные для автоматической публикации. Затем легитимный workflow релиза, использовавший механизм OIDC (OpenID Connect) от GitHub, опубликовал отравленные пакеты под автоматизированной учётной записью npm-oidc-no-reply@github[.]com. При этом пакеты получили действительные подписи происхождения (provenance), хотя исходные коммиты были неавторизованными.
Кампания прошла шесть фаз. На первом этапе была скомпрометирована инфраструктура пайплайна. Затем в один исходный файл каждого пакета внедрён сильно обфусцированный загрузчик. Третья фаза включала staged-релиз: сначала альфа-предрелиз, а через 24 минуты стабильный релиз с идентичной полезной нагрузкой, что расширило радиус поражения. Потребители загружали отравленные версии через обычное разрешение зависимостей npm и Yarn. При импорте пакета выполнялся код, порождающий скрытый дочерний процесс. Этот процесс загружал с IPFS файл sync.js и записывал его в специальный каталог NodeJS, специфичный для операционной системы.
Среда Miasma предоставляла зашифрованную начальную загрузку, закрепление, связь с C2-сервером, каналы возврата данных и устойчивое обнаружение через Nostr, Ethereum, BitTorrent DHT, libp2p и IPFS. Шесть дополнительных модулей реализованы, но отключены: сбор учётных данных, зашифрованная эксфильтрация, распространение по цепочке поставок, метаморфическая генерация, отравление AI-инструментов и обход песочницы.
Технически вредоносная нагрузка работает в несколько стадий. Стадия 0 намеренно не объявляет никаких npm-хуков жизненного цикла, чтобы обойти инструменты аудита, проверяющие только предустановку/постустановку. Стадия 1 выполняет загрузчик во время require и порождает скрытый дочерний процесс. Стадия 1b восстанавливает логику загрузки с IPFS во время выполнения, поэтому крупная вторая стадия не появляется в открытом виде в опубликованном пакете. Стадия 2 загружает и дешифрует файл sync.js размером около 8,2 МБ через три криптографических уровня, используя статически встроенные ключи. Стадия 3 инициализирует полную модульную среду Miasma с C2, закреплением и резервными каналами.
Настройки закрепления включают запись в реестр Windows (HKCU Run), systemd unit на Linux и RC-файлы оболочки на macOS. Первичные конечные точки C2 расположены по адресу 85.137.53[.]71 на портах 8080, 8081 и 8091. Среди резервных каналов - Nostr, Ethereum, BitTorrent DHT, libp2p и IPFS. Хотя модуль сбора учётных данных был отключён в этой сборке, он может воздействовать на более чем 100 переменных окружения (GITHUB_TOKEN, NPM_TOKEN, AWS_ACCESS_KEY и др.) и файлы учётных данных (.npmrc, .aws/credentials, id_rsa, .vault-token и т.д.).
Организациям необходимо немедленно удалить все пять скомпрометированных версий, очистить кеши npm и Yarn, проверить наличие файла sync.js в каталогах NodeJS, заблокировать исходящие соединения к 85.137.53[.]71 на портах 8080, 8081 и 8091, а также сменить все учётные данные, доступные из любой среды, которая импортировала заражённые пакеты. Защита Microsoft Defender Antivirus обнаруживает вредоносные артефакты под именами Trojan:JS/MiasmStealer.SC и Trojan:Script/Supychain.A, а Microsoft Defender for Endpoint обеспечивает поведенческое обнаружение подозрительных процессов Node.js и попыток получения файлов с IPFS.
Помимо технических мер, следует провести аудит собственных пайплайнов релизов. Инцидент демонстрирует уязвимость механизма доверенной публикации через GitHub Actions OIDC: автоматические публикации могут быть скомпрометированы при наличии доступа к токену бота. Рекомендуется ограничить области токенов, внедрить утверждение workflow, защищённые окружения, мониторинг аномалий при автоматической публикации и проверку подлинности происхождения артефактов. После ликвидации последствий необходимо пересобрать все проекты из известной чистой базы зависимостей, подтвердить отсутствие в кешах и репозиториях артефактов скомпрометированных хешей, а также перестроить базовые образы и золотые сборщики, чтобы будущие задания не наследовали заражённые кеши или закреплённое вредоносное ПО.
Индикаторы компрометации
Package
- @asyncapi/specs 6.11.2-alpha.1
- @asyncapi/specs 6.11.2
- @asyncapi/generator 3.3.1
- @asyncapi/generator-components 0.7.1
- @asyncapi/generator-helpers 1.1.1
IPv4 Port Combination
- 85.137.53.71:8080
- 85.137.53.71:8081
- 85.137.53.71:8091
URL
- https://ipfs.io/ipfs/Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf
Publisher identity
- npm-oidc-no-reply@github.com
SHA256
- 082d733db0687dcd768104972b065d4b58cb1e6043688c6c20fa3702337f36ab
- 24b9ee242f21a73b55f7bb3297eafb33c60840907386b542ed79fc6b72365168
- 34014776d3d3ff11bc4439b02fd7ac0f02a887eb3a052eeafff236e2f6db8ad1
- 6e78713b75bd34828d49896176627f7face7aa9036cd874f2e02d9f23a9a9c71
- 8351d251cf0b5a0bd82242deaa0a14e3e1394418d55c0f4259dac4303b79fc0c
- 9b2e65db653ca8575c9b10eefb9a80c6006404812c2ec212bf5675e3c690233b
- b270bdf8e2274ea1af0a6eed74d8f10e5fe61012d6cc226a43cc7cc7fd9f6292
- b9993a8ad0518849416798cf29668256ccb96598fc4423501ccab5312812653a
- bfaeb987faa6de2b5a5eb63b1233d055215b09b0349a9394f2175fd7cdf385e4
- d425e4583cc6185d41e95c45eda00550045a5d1919b9a012236a4520d009dbd7