4 серпня 2026 року в екосистемі npm зафіксовано масштабну атаку на ланцюг постачання: шкідливий код, уперше виявлений у [email protected], поширився за межі просторів імен Keyv і Cacheable, уразивши сотні пакетів багатьох організацій. Шкідливе ПЗ використовує механізм скриптів preinstall для викрадення облікових даних із середовищ розробки та CI/CD, а потім автоматично перевипускає заражені версії інших пакетів, доступних через викрадені npm-токени. Будь-яку систему, що виконала заражену версію, слід розглядати як скомпрометовану — при цьому перед ротацією токенів необхідно спочатку видалити встановлений шкідливим ПЗ спостерігач за відкликанням облікових даних, інакше ротація сама запустить обробник зловмисника.
Масштаб кампанії та розбіжності в оцінках
Оцінки масштабу зараження суттєво відрізняються між дослідницькими групами. За даними SafeDep, підтверджено 353 шкідливі версії у 79 пакетах реєстру npm, а моніторинг зафіксував ширше охоплення — 442 версії в 353 пакетах. Aikido повідомляє щонайменше про 868 пакетів і 1 381 заражену версію. Жодна з розширених оцінок не була незалежно відтворена на основі повного публічного списку станом на час підготовки матеріалу.
Принципово важливо: усі ці числа описують кількість шкідливих артефактів у реєстрі, а не число скомпрометованих систем. Фактичне зараження робочої станції чи CI-раннера залежить від того, чи була дозволена конкретна заражена версія в залежностях проєкту та чи виконався її lifecycle-скрипт.
Технічна анатомія атаки
Перший вектор: npm-пакет
Першою підтвердженою шкідливою версією стала [email protected]. У package.json було додано команду node setup.mjs як хук preinstall, а до пакета включено файли setup.mjs і Math_Symbol.js. Скомпільований код бібліотеки при цьому залишився без змін — функціональність пакета не порушувалася, що ускладнювало виявлення.
За даними SafeDep, перший етап перевіряє наявність середовища виконання Bun, за потреби завантажує версію 1.3.13 з офіційних GitHub-релізів, після чого передає керування скомпільованому бандлу розміром 727 680 байт. Цей бандл збирає широкий спектр секретів:
- Токени GitHub і npm
- Облікові дані хмарних сервісів
- Секрети HashiCorp Vault і Kubernetes
- Дані підключення до баз даних
- Приватні ключі
- Вміст пам’яті раннерів GitHub Actions
Socket незалежно підтвердив наявність у коді функцій модифікації, версіонування та перевипуску пакетів від імені викраденої npm-ідентичності — саме цей механізм забезпечує червеподібне поширення.
Другий вектор: хуки в репозиторії
Окрім npm-пакета, у репозиторії Keyv виявлено альтернативний шлях виконання шкідливого коду. Файл .claude/settings.json містить хук SessionStart, що викликає .vscode/setup.mjs. Файл .vscode/tasks.json містить задачу «Environment Setup» з параметром runOn: folderOpen, яка викликає .claude/setup.mjs. Коміт, що впровадив ці хуки, мав зелений значок верифікації GitHub і був підписаний від імені github-actions[bot]. Підтверджений підпис засвідчує лише коректність криптографічної операції, але не ідентифікує того, хто контролював облікові дані.
Ці хуки не виконуються безумовно. VS Code блокує автоматичні задачі у недовірених робочих просторах і типовим чином запитує підтвердження. Claude Code застосовує механізм довіри до налаштувань, що постачаються з репозиторію. Однак розробник, який звик автоматично надавати довіру до проєкту, фактично активує виконання шкідливого коду.
Станом на 17:40 IST 4 серпня обидва файли з хуками залишалися у гілці main, а core/keyv/package.json і надалі оголошував версію 6.0.0 зі шкідливим скриптом preinstall.
Обхід механізмів довіри
Заражений реліз Keyv пройшов через легітимний робочий процес GitHub Actions і отримав дійсну атестацію OpenID Connect (OIDC) та SLSA (Supply-chain Levels for Software Artifacts). Атестація коректно ідентифікувала процес збирання, але не могла встановити, що вихідний код, який надійшов у цей процес, був безпечним. Це демонструє фундаментальне обмеження: провенанс і підписи верифікують шлях збирання, але не вміст того, що було зібрано.
Зв’язок з попередніми атаками
Semgrep задокументував ідентичні хуки Claude Code і VS Code, ім’я файла setup.mjs та завантаження Bun 1.3.13 під час квітневої компрометації пакета lightning у PyPI. Aikido відносить серпневу активність до сімейства шкідливого ПЗ Shai-Hulud. Співпадіння артефактів підтверджує зв’язок на рівні сімейства шкідливого ПЗ, однак не встановлює, хто стоїть за серпневою кампанією — ані початковий вектор доступу, ані конкретний актор не ідентифіковані.
Наявні дані не дають змоги визначити, чи поширювався черв’як виключно від однієї викраденої ідентичності видавця, чи були задіяні незалежно скомпрометовані облікові записи кількох розробників.
Оцінка впливу
Під загрозою перебувають усі команди та організації, які використовують Keyv, Cacheable і пов’язані пакети у своїх проєктах. Keyv — популярна бібліотека для уніфікованого доступу до сховищ даних, що широко застосовується в екосистемі Node.js. Компрометація зачіпає не лише кінцеві застосунки, а й CI/CD-конвеєри, де lifecycle-скрипти виконуються автоматично.
Не всі пакети, пов’язані з оригінальним мейнтейнером, були заражені. За даними SafeDep, опубліковані адаптери @keyv/* і лінійка Keyv 5.x залишалися чистими. Водночас репозиторій становить окремий ризик: подальший коміт розмістив шкідливі файли в усіх 19 пакетах робочого простору, тому будь-який реліз, зібраний із зараженого дерева, міститиме шкідливий код.
Рекомендації щодо реагування
- Перевірте файли lockfile (
package-lock.json,yarn.lock,pnpm-lock.yaml) на наявність точних версій із зараженого набору. Не покладайтеся на поточні тегиlatest— вони змінювалися в ході інциденту. На момент спостереження для низки пакетів, включно з [email protected], [email protected] і [email protected], були відновлені безпечні версії. - Якщо заражена версія була встановлена й виконана — вважайте всі облікові дані на машині скомпрометованими.
- Перед ротацією токенів обов’язково знайдіть і видаліть спостерігача за відкликанням облікових даних, встановленого шкідливим ПЗ. Ротація без видалення спостерігача може запустити обробник зловмисника.
- Оновіть npm-клієнт до версії 12, яка блокує несанкціоновані lifecycle-скрипти залежностей за замовчуванням. Ранніші версії npm та альтернативні шляхи встановлення, які допускають lifecycle-скрипти, залишаються вразливими.
- Не використовуйте блокування за просторами імен як єдину захисну міру — це створює ризик як пропуску заражених версій, так і хибного блокування чистих релізів.
- Перевірте клони репозиторію Keyv на наявність файлів
.claude/settings.jsonі.vscode/tasks.jsonзі шкідливими хуками. Не надавайте довіру робочому простору до очищення репозиторію.
Станом на момент підготовки матеріалу ні мейнтейнер проєкту, ні npm, ні GitHub не випустили офіційної заяви про інцидент. Організаціям, які використовують уражені пакети, слід негайно провести аудит залежностей за точними версіями з файлів lockfile, видалити спостерігача шкідливого ПЗ перед будь-якою ротацією секретів і перейти на npm 12 для захисту від виконання несанкціонованих скриптів залежностей — саме цей механізм був ключовим вектором поширення черв’яка.