Червь в npm перешёл на запуск при импорте: установка без скриптов больше не защищает

Червь в npm перешёл на запуск при импорте: установка без скриптов больше не защищает

Отключение установочных скриптов давно стало первым советом при разборе очередного червя в npm. Теперь этого мало. 27 октября 2026 года в реестре лежит пакет @testsecuiitytestme/cache-helper, который запускает вредоносное ПО в момент, когда приложение подключает его к себе. Флаг --ignore-scripts, запрещающий выполнение скриптов при установке, такой запуск не останавливает.

Описание

С 19 по 27 октября реестр принял 19 пакетов от одного автора. Публиковали их четыре учётные записи, и следы ведут к тестовым репозиториям на GitHub, где уже разложены файлы червя. Схема выросла из двух источников: в июне 2026 года объявился червь Miasma с меткой Phantom Gyp, а с мая в открытом доступе лежат исходники Shai-Hulud. От первого здесь загрузчик, от второго - удаление данных при отзыве украденного токена. Родство с авторами Miasma публично не подтверждено. Код Shai-Hulud открыт, поэтому собрать похожий инструмент может кто угодно.

Механику запуска автор менял трижды за неделю. Сначала нагрузку запускала сборка нативного модуля при установке: для реестра это обычная компиляция. Потом появился сценарий, который подгружал готовую библиотеку и расшифровывал из неё полезную нагрузку. В последней версии библиотека срабатывает при регистрации в среде Node.js - пакет просто подключает её на входе. Любое приложение, импортировавшее пакет, стартует червя. При установке он тоже запускается, так что оба пути ведут к одному результату.

Дальше начинается сбор данных. Нагрузка выгребает ключи доступа, учётные данные пакетных реестров и хостов Git, содержимое файлов с переменными окружения, сохранённые логины браузеров, токены облачных и AI-сервисов. Отдельная цель - секреты сборочных систем: их достают из памяти процесса, который обслуживает сборку. В сборочных системах червь заодно глушит защитный агент, а при неудаче завершает работу. Украденное уходит в новый публичный репозиторий на аккаунте жертвы, и сообщение коммита несёт зашифрованный GitHub-токен. Другие заражённые машины ищут такие коммиты и переиспользуют токены.

Параллельно в системе прописываются две службы. Одна проверяет украденный токен каждые 45 секунд и держит вахту 48 часов. Увидев отказ после отзыва, она удаляет домашний каталог вместе с документами. Вторая раз в час ищет в коммитах GitHub метку msync-3f7a и забирает скрипт, подписанный ключом автора. По данным SafeDep, за всё время наблюдения сторонние пакеты не пострадали и реальных жертв нет: вся активность идёт с собственных тестовых аккаунтов.

Проверки, заточенные на сценарий установки, новые сборки пропускают. Зацепка, которая от сценариев не зависит, - готовый бинарник в каталоге предсобранных модулей при полном отсутствии исходников. Второй признак - крупный зашифрованный файл рядом с крошечной обёрткой, которая его читает. Ещё один повод присмотреться - пустая заглушка вместо нормального описания пакета в версии, которая уже не является черновой.

Реестр реагирует по мере обнаружения. Три пакета кластера npm заменил заглушками с пометкой 0.0.1-security, остальные просто убрал. Меньше чем через 20 часов автор завёл новую учётную запись и выложил очередную сборку. Сам червь при этом не ограничен npm: он копирует себя в другие реестры пакетов, рассылается по SSH на хосты из списка известных подключений и добавляет в чужие репозитории файлы для CI и AI-агентов. Коммиты при этом копируют автора и сообщение последнего настоящего коммита в ветке.

Флаг установки перестал быть границей между безопасной и опасной установкой. Граница теперь проходит по содержимому пакета.

Индикаторы компрометации

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