
Сканер для атаки на цепочку поставок keyv/cacheable: обнаруживает скомпрометированные npm-пакеты, проверяет хэши полезной нагрузки и находит импланты персистентности в режимах repo и host.
Английский | Português
Автономный сканер для инцидента в цепочке поставок keyv/cacheable («Shai-Hulud: Here We Go Again», 4 авг 2026) — 440+ npm-пакетов скомпрометировано самораспространяющимся червём, который крадёт облачные и CI-учётные данные и устанавливает персистентность с механизмом «мертвеца» (dead-man's switch).
Обнаруживает за минуты, без установки чего-либо:
package-lock.json, npm-shrinkwrap.json, yarn.lock (v1 и Berry), pnpm-lock.yaml и bun.lock — включая транзитивные зависимости, с полной цепочкой (например, eslint → file-entry-cache → flat-cache → [email protected]);node_modules (имя + SHA-256-хэш известных артефактов);SUSPECT, никогда не подтверждаются без хэша;.claude/settings.json и .vscode/tasks.json, временные артефакты (bun-dl-*);keyv/cacheable была скомпрометирована; атакующий опубликовал новые версии с хуком "preinstall": "node setup.mjs" — кодом, который выполняется до установки пакета, с правами того, кто запустил npm install.setup.mjs скачивает среду выполнения Bun из GitHub и запускает в ней полезную нагрузку — обход защиты, которая отслеживает только процессы node.Math_Symbol.js (~728 КБ, обфусцированный) крадёт учётные данные: метаданные инстансов AWS, ключи AWS/GCP/Azure, токены Vault, сервисные аккаунты Kubernetes, секреты GitHub Actions, npm-токены, плюс общий regex-поиск приватных ключей и bearer-токенов на диске.npm install/npm ci с включёнными скриптами жизненного цикла с 2026-08-04 09:35 UTC. С --ignore-scripts хук не выполнялся..claude/settings.json (SessionStart) и .vscode/tasks.json (folderOpen), которые запускают загрузчик при открытии клонированной папки — без npm install, ничего не устанавливается. Сюда входят те, кто клонировал репозиторий для расследования инцидента, и AI-агенты, открывшие директорию, — один из первых публичных случаев использования хуков AI-агентов (.claude/) как вектора атаки на цепочку поставок.Имплант устанавливает «watcher» (gh-token-monitor), который поддерживается в живых LaunchAgent (macOS) или пользовательским сервисом systemd + loginctl enable-linger (Linux). Каждые 60 секунд он проверяет украденный GitHub-токен через API. Пока токен работает, ничего не происходит. Когда ответ становится 4xx — то есть в момент отзыва токена — он выполняет через eval содержимое ~/.config/gh-token-monitor/handler: произвольную команду, заданную удалённо атакующим. Публичный анализ не знает, что там — это может быть уничтожение данных, повторная имплантация, программа-вымогатель или ничего. Риск не поддаётся оценке; именно поэтому порядок реагирования абсолютен.
Три свойства, которые меняют реагирование:
host.[email protected] вышел с валидной аттестацией SLSA. Происхождение (provenance) подтверждает целостность сборки, а не исходного кода: легитимный workflow компилировал уже троянизированный код.package.json (хук preinstall) и двух новых файлах, добавленных в пакет (setup.mjs, Math_Symbol.js).eslint → file-entry-cache → flat-cache → keyv. Поэтому сканер показывает цепочку в каждой находке.scan.mjs обладает следующими свойствами — это важно для любого, кто реагирует на инцидент в цепочке поставок:
npm install. Проверьте весь scan.mjs за 15 минут перед запуском.--update (загрузка свежего манифеста IOC), явная и необязательная.docker run --network=none или изолированная машина: просто скопируйте scan.mjs + iocs.json.Требование: Node.js ≥ 18 (на любой машине с npm он уже есть). Скачайте два файла — scan.mjs + iocs.json — и всё: никакой установки.
Внимание: если вы клонировали весь этот репозиторий, папка
fixtures/содержит инертные IOC, используемые в тестах (реальные имена и версии, фиктивное содержимое — без вредоносного ПО). Сканер пропускает её автоматически и предупреждает в выводе; находки из неё появятся, только если сканировать её намеренно.
Есть два режима запуска, отвечающих на разные вопросы, — и именно это определяет где запускать:
repo читает lock-файлы и node_modules — а lock-файлы живут в git, поэтому он может быть централизован: один человек сканирует все репозитории компании.host ищет имплант (watcher, LaunchAgent/systemd, хуки IDE), который живёт на машине, где выполнялся код — этого нет в git, и это нельзя централизовать.node scan.mjs repo /folder/with/all/the/repos --json=result.json --html=report.html
Отвечает на вопрос «какие проекты затронуты» за минуты, никого не привлекая. Принимает несколько путей; обходит поддиректории (включая монорепозитории и workspaces).
Для каждого проекта с находкой определите, кто трогал его с 2026-08-04 09:35 UTC (git log, логи CI). Эти люди запускают на своей машине:
node scan.mjs # current directory + host, in ~30 seconds
В область действия входят все, кто (a) запускал npm install/npm ci в этом окне; или (b) просто клонировал и открыл папку в VS Code или в AI-агенте — вектору B установка не нужна.