Около 09:00 UTC 4 августа атакующий получил контроль над аккаунтом Джареда Врея на GitHub . Используя доступ сопровождающего, он внёс вредоносный код непосредственно в ветку main репозитория keyv, а затем выпустил новые версии пакетов из семейств keyv и cacheable .
На первом этапе были затронуты 11 пакетов, включая keyv, cacheable-request, cache-manager, @cacheable/utils, flat-cache и file-entry-cache . Компрометацию независимо подтвердили специалисты Aikido Security, StepSecurity, Socket и Chainguard .
В каждый заражённый пакет добавлялись два файла — setup.mjs и Math_Symbol.js, — а в package.json появлялась команда:
"preinstall": "node setup.mjs"
Когда разработчик или CI-система запускали npm install, скрипт setup.mjs автоматически выполнялся до завершения установки. Этот загрузчик скачивал с GitHub Releases легитимный бинарный файл JavaScript-рантайма Bun, а затем запускал обфусцированную нагрузку второго этапа Math_Symbol.js размером примерно 710–728 КБ .
Microsoft Threat Intelligence подтвердила, что речь идёт о варианте Mini Shai-Hulud . Вредоносная программа собирала широкий набор секретов из окружения разработчика и систем сборки :
Главная опасность атаки заключалась в способности червя к самораспространению. Получив npm-токены с правом публикации и GitHub PAT из заражённой среды, он использовал их для выпуска вредоносных версий пакетов, принадлежащих другим, не связанным между собой сопровождающим .
Масштаб атаки рос по мере обнаружения новых заражений:
Червь пересекал границы npm-пространств имён: он не ограничился семействами keyv и cacheable, а переместился в пакеты, связанные, среди прочих, с Deliveroo, Ornikar, OneReach, Picsart, Qlik и ServiceTitan .
Собранные учётные данные отправлялись в репозиторий GitHub, контролируемый атакующим. Червь мог создать новый репозиторий для этой цели либо использовать выделенный репозиторий для эксфильтрации данных . Вредоносная нагрузка включала несколько резервных каналов вывода данных, поэтому блокировка одного из них не обязательно останавливала операцию .
Исследователи рекомендовали считать полностью скомпрометированной любую систему, на которой выполнялась установка затронутой версии пакета. Удалить несколько вредоносных файлов недостаточно: секреты могли быть прочитаны до того, как заражение стало заметным.
Немедленно закрепите или откатите затронутые пакеты до известных безопасных версий. Для защиты от случайной повторной установки заражённых релизов используйте механизмы overrides в npm, yarn или pnpm .
Проверьте lock-файлы — package-lock.json, yarn.lock и pnpm-lock.yaml, — включая транзитивные зависимости, которые проект подключает не напрямую .
Если на компьютере или CI/CD-раннере выполнялся npm install с затронутой версией, не ограничивайтесь удалением setup.mjs и Math_Symbol.js . Исходите из того, что все секреты, доступные этому хосту, могли быть украдены.
Необходимо отозвать и создать заново потенциально скомпрометированные учётные данные :
Это важная деталь порядка действий. В некоторых случаях вредоносная программа создавала GitHub workflow-наблюдатели, способные перехватить или повторно раскрыть новый токен сразу после его выпуска . Поэтому исследователи советовали сначала отключить или удалить такие механизмы мониторинга, и только затем приступать к ротации секретов .
Очистите кэши npm, pnpm и yarn, а также кэши сборки Docker на рабочих станциях разработчиков и CI/CD-раннерах . Все артефакты следует пересобрать с нуля, чтобы заражённые зависимости не сохранились в кэше сборки или слоях Docker .
Проведите аудит недавно созданных репозиториев, подозрительных workflow и несанкционированных коммитов . Отдельно проверьте возможные артефакты закрепления в окружении, в том числе .claude/settings.json и .vscode/tasks.json .
Атака 4 августа показала, насколько быстро один скомпрометированный аккаунт сопровождающего может превратить проблему отдельного npm-пакета в масштабный инцидент цепочки поставок. Злоумышленники использовали доверенный канал публикации, легитимный бинарник Bun для запуска нагрузки, украденные токены для самораспространения и несколько каналов эксфильтрации .
Для команд разработки это ещё одно напоминание о необходимости фиксировать версии зависимостей, по возможности отключать скрипты preinstall и postinstall, отслеживать необычную активность в GitHub и заранее иметь план реагирования на компрометацию программных зависимостей.