Защитите свое предприятие от червя Shai-Hulud и уязвимости в npm прямо сейчас с помощью 6 практических шагов

Защитите свое предприятие от червя Shai-Hulud и уязвимости в npm прямо сейчас с помощью 6 практических шагов

Источник: VentureBeat · Louis Columbus

Любая среда разработки, которая установила или импортировала один из 172 скомпрометированных пакетов npm или PyPI, опубликованных после 11 мая, должна рассматриваться как потенциально скомпрометированная. На зараженных рабочих станциях разработчиков червь собирает учетные данные из более чем 100 путей к файлам: ключи AWS, закрытые ключи SSH, токены npm, персональные токены доступа GitHub (PAT), токены HashiCorp Vault, служебные учетные записи Kubernetes, конфигурации Docker, историю оболочки и криптовалютные кошельки. По данным SecurityWeek, впервые в рамках кампании TeamPCP он атакует менеджеры паролей, включая 1Password и Bitwarden.

Он похищает конфигурации AI-агентов Claude и Kiro, включая токены аутентификации MCP-серверов для каждого внешнего сервиса, к которому подключается агент. И он не исчезает после удаления пакета.

Червь устанавливает механизм закрепления в Claude Code (.claude/settings.json) и VS Code (.vscode/tasks.json с параметром runOn: folderOpen), которые перезапускаются при открытии каждого проекта, а также системный демон (macOS LaunchAgent / Linux systemd), переживающий перезагрузки. Они находятся в дереве проекта, а не в node_modules. Удаление пакета не стирает их. На CI-раннерах червь напрямую читает память процессов раннера через /proc/pid/mem для извлечения секретов (включая замаскированные) на раннерах под управлением Linux. Если отозвать токены до изоляции машины, то, согласно анализу компании Wiz, деструктивный демон полностью очистит вашу домашнюю директорию.

В промежуток с 19:20 по 19:26 UTC 11 мая червь Mini Shai-Hulud опубликовал 84 вредоносные версии в 42 пакетах @tanstack/* на npm. В течение 48 часов кампания расширилась до 172 пакетов (403 вредоносные версии) на npm и PyPI, согласно данным мониторинга Mend. Только у @tanstack/react-router насчитывается 12,7 миллиона загрузок в неделю. CVE-2026-45321, оценка CVSS — 9,6. Компания OX Security сообщила о 518 миллионах затронутых кумулятивных загрузок. Каждая вредоносная версия имела действительное подтверждение происхождения (provenance) по стандарту SLSA Build Level 3. Происхождение было подлинным. Пакеты были заражены.

«У TanStack на бумаге все было настроено правильно: доверенная публикация OIDC, подписанное происхождение, двухфакторная аутентификация для каждой учетной записи мейнтейнера. Атака все равно сработала», — рассказал Пейтон Кеннеди (Peyton Kennedy), старший специалист по исследованию безопасности в компании Endor Labs, в эксклюзивном интервью VentureBeat. — «Техника осиротевших коммитов показывает, что реальным инструментом контроля здесь является область видимости (scope) OIDC, а не происхождение и не 2FA. Если ваш конвейер публикации доверяет всему репозиторию целиком, а не конкретному воркфлоу в конкретной ветке, коммита без истории родителей и привязки к ветке достаточно для получения действительного токена публикации. Это проблема конфигурации, решаемая одной строкой кода».

Три уязвимости, объединенные в одного червя с подтвержденным происхождением

Отчет TanStack о разборе инцидента описывает всю цепочку атак. 10 мая злоумышленник сделал форк репозитория TanStack/router под именем zblgg/configuration, выбранным во избежание поиска по списку форков, согласно анализу Snyk. Запрос на слияние (pull request) инициировал выполнение воркфлоу pull_request_target, который выкачал код из форка и запустил сборку, предоставив злоумышленнику выполнение кода на раннере TanStack. Злоумышленник отравил кэш GitHub Actions. Когда легитимный мейнтейнер выполнил слияние с веткой main, релизный воркфлоу восстановил отравленный кэш. Бинарные файлы злоумышленника прочитали /proc/pid/mem, извлекли токен OIDC и отправили POST-запрос напрямую на registry.npmjs.org. Тестирование завершилось неудачно. Публикация была пропущена. При этом 84 подписанных пакета все равно попали в реестр.

В отчете указано: «Каждая уязвимость преодолевает границу доверия, на которую рассчитывали остальные». Это методы из мартовской атаки 2025 года на tj-actions/changed-files, скомбинированные в новом контексте.

Всего за несколько часов червь перекинулся с npm на PyPI

Microsoft Threat Intelligence подтвердила, что пакет mistralai версии 2.4.6 для PyPI выполняет код в момент импорта (а не установки), загружая полезную нагрузку, замаскированную под Hugging Face Transformers. Средства защиты npm (проверка lock-файлов, —ignore-scripts) не покрывают выполнение кода при импорте в Python.

Компания Mistral AI опубликовала бюллетень по безопасности, подтверждающий масштаб последствий. Скомпрометированные пакеты npm были доступны в период с 22:45 UTC 11 мая до 01:53 UTC 12 мая (примерно три часа). Релиз PyPI mistralai==2.4.6 помещен в карантин. В Mistral заявили, что было задействовано устройство пострадавшего разработчика, однако инфраструктура самой компании не подверглась компрометации. Компания SafeDep подтвердила, что Mistral никогда не выпускала версию 2.4.6: 11 мая не было зафиксировано никаких коммитов и никаких тегов.

Компания Wiz задокументировала полный радиус поражения: 65 пакетов UiPath, SDK Mistral AI, OpenSearch, Guardrails AI, 20 пакетов Squawk. StepSecurity связывает эту кампанию с группировкой TeamPCP на основе совпадения цепочки инструментов с предыдущими волнами Shai-Hulud, а также с атаками на CLI Bitwarden и Trivy. Червь работает под управлением среды Bun, а не Node.js, чтобы обходить мониторинг безопасности Node.js.

Злоумышленник рассматривал ИИ-агентов написания кода как часть доверенной среды выполнения

Технический анализ Socket полезной нагрузки router_init.js размером 2,3 МБ выявляет десять параллельно работающих классов сбора учетных данных. Червь записывает механизмы закрепления в директории .claude/ и .vscode/, перехватывая конфигурацию SessionStart в Claude Code и механизм запуска задач folder-open в VS Code. Деобфускация, выполненная StepSecurity, подтвердила, что червь также собирает конфигурации MCP-серверов Claude и Kiro (~/.claude.json, ~/.claude/mcp.json, ~/.kiro/settings/mcp.json), в которых хранятся ключи API и токены аутентификации для внешних сервисов. Это ранний, но подтвержденный случай, когда вредоносное ПО цепочки поставок рассматривает конфигурации ИИ-агентов как ценные цели для кражи учетных данных. Описание токена npm, которое устанавливает червь, гласит: «IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner» («Если вы отзовете этот токен, компьютер владельца будет стерт»). И это не блеф.

«Что меня поразило в этой полезной нагрузке, так это то, где она закрепилась после запуска», — рассказал Кеннеди изданию VentureBeat. — «Она прописала хуки персистентности в конфигурацию SessionStart для Claude Code и в инструмент запуска задач по открытию папки для VS Code, чтобы перезапускаться при каждом открытии проекта разработчиком — даже после удаления пакета npm. Злоумышленник отнесся к ИИ-агенту написания кода как к части доверенной среды выполнения, каковой он по сути и является. Эти инструменты читают ваш репозиторий, выполняют команды оболочки и имеют доступ к тем же секретам, что и разработчик. Обеспечение безопасности среды разработки теперь означает необходимость думать об агентах, а не только о пакетах».

Таблица аудита цепочки доверия CI/CD

Шесть брешей, которые использовал Mini Shai-Hulud. Как устроен ваш CI/CD сегодня. Контрольные меры для закрытия каждой бреши.

Вопрос аудита

Как ваш CI/CD устроен сегодня

Брешь

1. Привяжите доверенную публикацию OIDC к конкретному файлу воркфлоу в конкретной защищенной ветке. Ограничьте разрешение id-token: write исключительно задачей публикации. Убедитесь, что эта задача выполняется из чистого рабочего пространства без восстановления недоверенного кэша

Большинство организаций предоставляют доверие OIDC на уровне репозитория. Любой воркфлоу в репозитории может запросить токен публикации. Разрешение id-token: write часто задается на уровне всего воркфлоу, а не ограничивается конкретной задачей публикации.

Червь добился выполнения кода внутри легитимного релизного воркфлоу путем отравления кэша, после чего извлек OIDC-токен из памяти процесса раннера. Сама по себе привязка к ветке или воркфлоу не остановила бы эту атаку, поскольку вредоносный код уже выполнялся внутри закрепленного воркфлоу. Полное исправление требует привязки ПЛЮС ограничения id-token: write только задачей публикации ПЛЮС гарантии использования этой задачей чистого, неразделяемого кэша.

2. Относитесь к происхождению по стандарту SLSA как к необходимому, но недостаточному условию. Добавьте поведенческий анализ во время установки

Команды считают действительный значок происхождения Sigstore доказательством безопасности пакета. Проверки npm audit signatures проходят успешно. Значок горит зеленым. Рабочие процессы закупщиков и отдела комплаенса принимают происхождение в качестве фильтра.

Все 84 вредоносных версии TanStack имеют действительные подтверждения происхождения SLSA Build Level 3. Это первый широко известный червь для npm с пакетами, имеющими валидные аттестации. Происхождение подтверждает, где пакет был собран, а не то, была ли сборка авторизована. ИИ-сканер Socket обнаружил все 84 артефакта в течение шести минут после публикации. Проверка происхождения не зафиксировала ничего.

3. Изолируйте кэш GitHub Actions по границам доверия. Аннулируйте кэши после подозрительных PR. Никогда не извлекайте и не запускайте код форков в воркфлоу pull_request_target

Воркфлоу, запускаемые из форков, и релизные воркфлоу используют одно и то же пространство имен кэша. Закрытие или откат вредоносного PR воспринимаются как восстановление чистого состояния. Триггер pull_request_target широко используется для бенчмаркинга и анализа размера бандла с выкачкой PR из форка.

Злоумышленник отравил хранилище pnpm через запущенный из форка pull_request_target, который выкачал и выполнил код форка на базовом раннере. Кэш пережил закрытие PR. Следующий легитимный релизный воркфлоу восстановил отравленный кэш при слиянии. actions/cache@v5 использует внутренний токен раннера для сохранения кэша, а не GITHUB_TOKEN воркфлоу, поэтому права permissions: contents: read не предотвращают модификацию. Кеннеди: «Правила защиты веток не распространяются на коммиты, которые не находятся ни в одной ветке, так что весь этот уровень укрепления не помог».

4. Проверьте optionalDependencies в lock-файлах и графах зависимостей. Блокируйте ссылки github:, указывающие на нерелизные коммиты

Статический анализ и принудительное использование lock-файлов сосредоточены на зависимостях dependencies и devDependencies. Зависимости optionalDependencies со ссылками на коммиты github: не фиксируются большинством инструментов.

Червь внедрил optionalDependencies, указывающие на осиротевший коммит github: в форке злоумышленника. Когда npm разрешает зависимость github:, он клонирует указанный коммит и автоматически запускает хуки жизненного цикла (включая prepare). Полезная нагрузка выполнилась до завершения собственного шага установки основного пакета. SafeDep подтвердила, что Mistral никогда не выпускала версию 2.4.6; коммиты не производились, теги отсутствуют.

5. Проверяйте импорты Python-зависимостей отдельно от средств контроля npm. Охватите конвейеры ИИ/МО, использующие guardrails-ai, mistralai или любые скомпрометированные пакеты PyPI

Средства защиты npm (принудительное использование lock-файлов, —ignore-scripts) применяются к стеку JavaScript. Считается, что пакеты Python безопасны, если завершилась команда pip install. Конвейеры CI для ИИ/МО рассматриваются как внутренняя инфраструктура тестирования, а не как цели атак на цепочку поставок.

Microsoft Threat Intelligence подтвердила, что пакет mistralai PyPI v2.4.6 выполняет код при импорте, а не при установке. Внедренный код в __init__.py загружает полезную нагрузку, замаскированную под Hugging Face Transformers. Флаг —ignore-scripts не имеет значения для выполнения кода во время импорта Python. Пакет guardrails-ai@0.10.1 также выполняется при импорте. Любой репозиторий с агентами, имеющий разрешение GitHub Actions id-token: write, уязвим к тому же методу извлечения OIDC. Ключи API LLM, учетные данные векторных БД и токены внешних сервисов попадают в радиус поражения.

6. Изолируйте и сделайте образы затронутых машин до отзыва украденных токенов. Не отзывайте токены npm до криминалистического сохранения хоста

Стандартное реагирование на инциденты: сначала отозвать скомпрометированные токены, затем провести расследование. Список токенов npm и немедленный отзыв — инстинктивный первый шаг.

Червь устанавливает постоянный демон (macOS LaunchAgent / Linux systemd), который опрашивает GitHub каждые 60 секунд. При обнаружении отзыва токена (ошибка 40X) он запускает команду rm -rf ~/, очищая домашнюю директорию. Описание токена npm гласит: «IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner». Microsoft сообщила о геофенсинговом деструктивном поведении: шанс 1 к 6 выполнения команды rm -rf / на системах, которые кажутся находящимися в Израиле или Иране. Кеннеди: «Даже после удаления пакета полезная нагрузка все еще может оставаться в .claude/ с хуком SessionStart, указывающим на нее. Команда rm -rf node_modules не удаляет это».

Источники: разбор инцидента TanStack, StepSecurity, Socket, Snyk, Wiz, Microsoft Threat Intelligence, Mend, Endor Labs. 12 мая 2026 г.

План действий директора по безопасности

  • Сегодня: «Самая быстрая проверка — это выполнение команд find . -name ‘router_init.js’ -size +1M и grep -r ’79ac49eedf774dd4b0cfa308722bc463cfe5885c’ package-lock.json», — сказал Кеннеди. Если хотя бы одна из них дает результат, немедленно изолируйте машину и сделайте ее образ. Не отзывайте токены до тех пор, пока хост не будет криминалистически сохранен. Деструктивный демон червя срабатывает при отзыве. Как только машина изоолирована, ротируйте учетные данные в следующем порядке: сначала токены npm, затем PAT GitHub, затем облачные ключи. Ищите артефакты персистентности .claude/settings.json и .vscode/tasks.json во всех проектах, которые были открыты на зараженной машине.

  • На этой неделе: Ротируйте все учетные данные, доступные с зараженных хостов: токены npm, PAT GitHub, ключи AWS, токены Vault, сервисные аккаунты K8s, ключи SSH. Проверьте свои пакеты на предмет неожиданных версий после 11 мая с коммитами от claude@users.noreply.github.com. Заблокируйте домены filev2.getsession[.]org и git-tanstack[.]com.

  • В этом месяце: Проведите аудит каждого воркфлоу GitHub Actions на предмет шести вышеуказанных уязвимостей. Привяжите публикацию OIDC к конкретным воркфлоу в защищенных ветках. Изолируйте ключи кэша по границам доверия. Установите параметр npm config set min-release-age=7d. Для команд ИИ/МО: проверьте guardrails-ai и mistralai на предмет скомпрометированных версий, проведите аудит конвейеров CI на предмет воздействия id-token: write и ротируйте каждый ключ API LLM и учетные данные векторной БД, доступные из CI.

  • В этом квартале (на уровне совета директоров): Финансируйте внедрение поведенческого анализа на уровне реестра пакетов. Простая верификация происхождения больше не является достаточным критерием закупки для инструментов безопасности цепочки поставок. Требуйте проведения аудитов безопасности CI/CD в рамках оценки рисков поставщиков для любого инструмента, имеющего доступ с правом публикации в ваши реестры. Установите правило, согласно которому ни один воркфлоу с разрешением id-token: write не запускается из общего кэша. Обращайтесь с конфигурациями ИИ-агентов написания кода (.claude/, .kiro/, .vscode/) как с хранилищами учетных данных, подлежащими тем же средствам контроля доступа, что и хранилища облачных ключей.

Червь эволюционирует. Защитники должны поступать так же

Это уже пятая волна Shai-Hulud за восемь месяцев. Четыре пакета SAP превратились в 84 пакета TanStack за две недели. Пакет intercom-client@7.0.4 пал 29 часов спустя, подтвердив активное распространение через украденную инфраструктуру CI/CD. Поздно вечером 12 мая коллектив исследователей вредоносного ПО vx-underground сообщил, что полностью вооруженный код червя Shai-Hulud был опубликован в открытом доступе. Если это подтвердится, значит, атака больше не ограничивается группировкой TeamPCP. Любой злоумышленник теперь может развернуть ту же цепочку отравления кэша, извлечения OIDC и публикации с подтвержденным происхождением против любого пакета npm или PyPI с неправильно настроенным конвейером CI/CD.

«Мы отслеживаем это семейство кампаний с сентября 2025 года», — рассказал Кеннеди. — «Каждая волна выбирала цель с большим числом загрузок и представляла более технически интересный вектор доступа. Техника осиротевших коммитов здесь поистине новаторская. Правила защиты веток не распространяются на коммиты, которые не находятся ни в одной ветке. Сфера безопасности цепочки поставок потратила много сил на происхождение и доверенную публикацию за последние два года. Эта атака прошла сквозь оба этих средства контроля, потому что пробел был не в подписи. Пробел был в области видимости».

Происхождение говорит вам, где был собран пакет. Оно не говорит вам, была ли сборка авторизована. Именно эту брешь призван закрыть данный аудит.

Безопасность

Смотреть все

Подпишитесь на свежие новости!

Глубокая аналитика для руководителей в области корпоративного ИИ, данных и безопасности

Подписаться по RSS

RSS-ленты обновляются каждые 15 минут.