Атака на цепочку поставок AsyncAPI: компрометация npm-пакетов через GitHub Actions и модуль Miasma

Атака на цепочку поставок NPM

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

Комментарии: 0