Крестовина марионетки из тёмного металла лежит на антистатическом коврике. Светящаяся янтарная нить тянется от разорванного листа к шестерёнке в падении.


Два независимых исследования - JAW и TaintAWI [препринты; venue и arXiv ID не верифицированы] - просканировали более 13 тысяч агентских workflow в GitHub Actions. Если их результаты подтвердятся, threat model для CI/CD-пайплайнов придётся серьёзно пересматривать. По заявлениям команды TaintAWI, фреймворк обнаружил 496 предположительно подтверждённых уязвимостей в 10 792 репозиториях, из которых 343 - ранее неизвестные zero-day. Параллельно JAW, по их данным, продемонстрировал end-to-end перехват 4 174 workflow и 8 шаблонов n8n, затронув 15 широко используемых GitHub Actions - official actions от Google, Anthropic, OpenAI и других. Новый класс уязвимостей - Agentic Workflow Injection - сидит на стыке prompt injection (OWASP LLM01:2025) и Poisoned Pipeline Execution (T1677, Execution). Ни классический анализ workflow, ни jailbreaking LLM по отдельности его не покрывают.

Таксономия AWI: почему это не обычная prompt injection LLM-агента

Agentic Workflow Injection (AWI) отличается от классической инъекции промптов по трём конкретным параметрам.

Первое: атакующий контролирует не весь промпт, а только фрагмент - заголовок issue, тело pull request, текст комментария или commit message. Остальная часть задана шаблоном workflow и недоступна для модификации.

Второе: цель атаки - не сама LLM, а привилегированные инструменты, которые агент вызывает в контексте CI/CD: gh issue edit, run_shell_command, запись в файлы, публикация комментариев.

Третье: импакт выходит далеко за рамки модели - эксфильтрация GITHUB_TOKEN, облачных ключей, манипуляция репозиторием и компрометация downstream-сборок.

По классификации OWASP, AWI задействует два риска одновременно. LLM01:2025 (Prompt Injection) - crafted input меняет поведение модели, обходя safety controls. LLM06:2025 (Excessive Agency) - агент располагает избыточными привилегиями и превращает семантическую инъекцию в реальный ущерб через выполнение системных команд.

TaintAWI формализует два конкретных паттерна AWI.

Prompt-to-Agent (P2A) - недоверенный контент из GitHub event context (issue body, PR description, комментарий) попадает в prompt boundary агента и напрямую влияет на его действия через tool calls. Прямой путь: вредоносный текст → промпт → модель интерпретирует как инструкцию → агент вызывает привилегированный инструмент.

Prompt-to-Script (P2S) - более хитрый паттерн. Атакующий влияет на output модели, который потребляется downstream-скриптом или следующим шагом workflow. LLM тут - посредник: вредоносный текст формирует ответ модели, ответ интерполируется в shell-команду или API-вызов следующего step.

Обе цепочки принципиально отличаются от традиционных script injection в GitHub Actions, где атакующий контролирует синтаксис интерпретатора. AWI работает через семантическое влияние на агента: никакого '; rm -rf /;' - вместо этого осмысленные инструкции на естественном языке, которые агент исполняет добровольно. Вот это и пугает.

Место в цепочке атаки​

AWI - не изолированная техника, а attack primitive, который встраивается в supply chain attack. Типичная цепочка выглядит так: атакующий начинает с Initial Access через создание issue в публичном репозитории (T1195.001, Compromise Software Dependencies and Development Tools), payload обрабатывается workflow (T1677, Poisoned Pipeline Execution), агент выполняет shell-команды (T1059.004, Unix Shell), получает доступ к секретам из environment variables (T1552.001, Credentials In Files), собирает данные репозитория (T1213.003, Code Repositories) и эксфильтрирует их через редактирование issue body (T1041, Exfiltration Over C2 Channel). Обфускация payload - стандартный приём для обхода базовых фильтров (T1027.010, Command Obfuscation).

Время от создания malicious issue до эксфильтрации секретов - от нескольких секунд до пары минут, ограниченное лишь временем запуска runner. Человеческий review в цепочке отсутствует полностью. Создал issue - получил токены. Автоматика.

Уязвимости GitHub Actions: поверхность атаки в агентских workflow​

Масштаб проблемы определяется двумя вещами: количеством агентских Actions в хозяйстве GitHub и тем, насколько небрежно они обрабатывают недоверенный вход.

По данным авторов TaintAWI, фреймворк проанализировал 1 033 AI-assisted Action с GitHub Marketplace. Результат: только 21 action из 1 033 даёт явный механизм access control для caller identity. Подавляющее большинство не позволяют workflow-автору ограничить, кто именно может триггерить агента. Любой зарегистрированный пользователь GitHub, создавший issue в публичном репозитории, потенциально запускает агентский workflow. Двадцать один из тысячи. Два процента.

JAW расширяет анализ на конкретные actions, подтвердив уязвимости в 15 из них.

Gemini CLI (google-github-actions/run-gemini-cli) - official Action от Google для issue triage. Публичные описания указывают на наличие уязвимости класса AWI (конкретный advisory/GHSA-ID не верифицирован). Агент получал GEMINI_API_KEY и GITHUB_TOKEN, имел доступ к run_shell_command и gh issue edit. Полный набор для катастрофы.

Claude Code Actions (anthropic/claude-code-action) - один из самых популярных агентских Actions. При конфигурации allowed_non_write_users: "*" проверка прав отключается полностью, а автономные tool calls Claude делают эксплуатацию возможной даже без прямого встраивания user input в промпт.

OpenAI Codex Actions - содержит защиту по умолчанию (policy drop-sudo), но комбинация allow-users: "*" с небезопасными параметрами security_policy открывает path к эксплуатации. Дефолт относительно безопасен, ошибки конфигурирования - нет.

GitHub AI Inference - формально не полноценный агент, но при включённом enable-github-mcp: true взаимодействует с MCP-сервером через привилегированные GitHub-токены, расширяя attack surface.

Помимо GitHub, JAW обнаружил 8 уязвимых шаблонов в n8n - популярной workflow-платформе для автоматизации, с двумя затронутыми official nodes. Первое подтверждение того, что AWI не ограничивается GitHub.

Когда AWI эксплуатабельна: условия и ограничения​

УсловиеКак проверитьТипичное состояние в wild
Недоверенный вход в промпт${{ github.event.issue.[I] }} или ${{ github.event.pull_request.[/I] }} в prompt/envПрисутствует в подавляющем большинстве issue-triage workflow
Привилегированные tool callsshell_command, issue_edit, pr_comment в toolsetВключены по умолчанию
Отсутствие валидации outputНет post-processing между ответом LLM и действиемОтсутствует в большинстве workflow
Отсутствие access controlНет allowed_users ограниченияПодавляющее большинство actions не имеют caller identity проверки

Если хотя бы одно условие из первых трёх отсутствует - AWI неэксплуатабельна. На практике большинство агентских workflow удовлетворяют всем трём: разработчики подключают Actions ради автоматизации, выдают GITHUB_TOKEN с write permissions и не фильтруют ни вход, ни выход. Классическое «работает - не трогай» в его худшем проявлении.

Kill chain AWI: MITRE ATT&CK mapping для атак на CI/CD pipeline​

ЭтапMITRE ATT&CKДействие атакующего
Initial AccessT1195.001, Compromise Software DependenciesСоздание issue/PR с payload в публичном репозитории
ExecutionT1677, Poisoned Pipeline ExecutionWorkflow автоматически запускается по событию
ExecutionT1059.004, Unix ShellАгент вызывает shell через tool call
Credential AccessT1552.001, Credentials In FilesЧтение GITHUB_TOKEN, API keys из env variables
CollectionT1213.003, Code RepositoriesСбор файлов репозитория, конфигураций, секретов
ExfiltrationT1041, Exfiltration Over C2 ChannelЗапись секретов в issue body через gh issue edit
Defense EvasionT1027.010, Command ObfuscationМаскировка payload под «дополнительные инструкции»

Применимость: атака работает на любом публичном или приватном репозитории с агентскими workflow при выполнении условий из таблицы выше. Для публичных репозиториев барьер входа минимальный - создание issue доступно любому. Для приватных - нужны права collaborator или возможность открыть PR через fork.

Prompt-to-Agent: компрометация CI/CD через LLM на примере Gemini CLI​

Самый цитируемый PoC - P2A-атака на google-github-actions/run-gemini-cli, описанная в нескольких публичных блогах security-исследователей (конкретный advisory/GHSA-ID не верифицирован). PoC приводится ниже в иллюстративной форме; точные version-bounds уязвимых версий Action публично не задокументированы.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме


Сама уязвимость - классическая script injection: workflow интерполирует список изменённых файлов из PR в bash-скрипт. Принципиально новое: атакующей стороной выступает AI-агент, использующий LLM для автоматической идентификации уязвимых workflow и генерации эксплойтов. Ранний индикатор того, что AI-агенты начинают применяться не только для защиты, но и для атаки CI/CD-инфраструктуры.

Среди защитных мер, описываемых как эффективные: LLM-driven code review для автоматической классификации PR, замена long-lived PAT на short-lived OIDC-токены, удаление неиспользуемых Actions secrets, enforcement branch protection с mandatory commit signing.

Детекция AWI: безопасность AI-агентов DevOps в масштабе экосистемы​

Два исследовательских фреймворка предлагают принципиально разные подходы к обнаружению инъекций в рабочие процессы агентов.

TaintAWI: статический taint-анализ​

TaintAWI работает в четыре этапа. Первый - характеризация actions: из 1 033 AI-assisted actions извлекаются taint-спецификации (prompt boundaries, derived outputs, agentic capabilities, access-control interfaces). Второй - построение IR: workflow YAML транслируется в семантическое промежуточное представление, нормализующее trigger entry points, job-level control flow и step-level data interfaces. Третий - Agentic Workflow Dependency Graph (AWDG), связывающий cross-boundary control и data dependencies между steps и jobs. Четвёртый - taint propagation от untrusted event context до agent prompt inputs и security-sensitive sinks.

Результаты (по данным авторов, требует верификации): 519 potential findings, 496 confirmed exploitable (заявленная precision 95.6%), 343 zero-day. Из 187 приоритизированных disclosure получено 26 ответов от maintainers, 24 приняты или исправлены. Неплохой hit rate для статического анализа.

JAW: Context-Grounded Evolution​

JAW использует гибридный подход. Path-sensitive workflow analysis строит guarded workflow graph (GWG) для определения feasible agent-invocation paths. Dynamic prompt-provenance analysis отслеживает, как attacker-controlled data формируется в LLM-промпт в runtime. Agent capability profiling восстанавливает доступные tools и ограничения агента. На базе этого контекста JAW итеративно генерирует и эволюционирует jailbreak-промпты, учитывающие конкретные guardrails конкретного агента.

JAW не только детектирует, но и генерирует working PoC-эксплойты. Результаты (по данным авторов, требует верификации): 4 174 hijackable workflow, 8 n8n-шаблонов. Bug bounties, по заявлению исследователей, получены от GitHub, Google, Anthropic и Snowflake.

Сравнение подходов: когда что применять​

КритерийTaintAWIJAW
МетодСтатический taint-анализГибрид: статика + динамика + LLM
СкоростьБыстрый, масштабируемыйМедленнее (требует runtime-анализа)
Подтверждение exploitabilityThreat model, без PoCEnd-to-end PoC-генерация
Покрытие платформGitHub ActionsGitHub Actions + n8n
False positive rate~4.4%Не раскрыт
Когда использоватьМассовый скрининг тысяч workflowГлубокий анализ конкретного target
Когда не использоватьНужен working exploitНужен быстрый scan

На практике: TaintAWI - первый проход, массовый скрининг. JAW - второй проход, подтверждение exploitability и генерация PoC. Существуют также open-source Opengrep-правила для базовой детекции prompt injection паттернов в workflow - быстрый lightweight-вариант, отслеживающий интерполяцию ${{ github.event.issue.[I] }} и ${{ github.event.pull_request.[/I] }} в prompt-полях при наличии AI-related actions. Для быстрой проверки «а не горим ли мы» - этого хватит за глаза.

Архитектурные контрмеры: GitHub Actions безопасность для агентских workflow​

GitHub опубликовал архитектуру защиты Agentic Workflows, основанную на четырёх принципах.

Zero-secret agents. Агент выполняется в изолированном контейнере без прямого доступа к секретам. LLM auth tokens размещаются в отдельном API proxy, MCP-серверы запускаются в trusted container с эксклюзивным доступом к authentication material. Host filesystem монтируется read-only, writable surface ограничивается через tmpfs overlays, агент работает в chroot jail - kernel-enforced изоляция, при которой даже arbitrary code execution внутри контейнера не даёт доступа к секретам.

Staged writes. Все write-операции агента проходят через staging: workflow декомпозируется на этапы с определёнными data artifacts и допустимыми consumers. Агент не публикует comment и не редактирует issue напрямую - все writes ветируются перед применением.

Network isolation. Private network между агентом и firewall. MCP access через trusted gateway. Блокирует DNS-exfiltration и прямые HTTP-запросы к attacker-controlled серверам.

Comprehensive logging. Все tool calls, file modifications, network requests логируются. Audit trail позволяет восстановить полную цепочку действий агента post-factum.

Decision tree: оценка уязвимости workflow​

  1. Используется ли AI-assisted Action? Нет - workflow не подвержен AWI. Да → шаг 2.
  2. Интерполируются ли github.event.* в prompt, env или run? Нет - низкий риск (проверьте P2S через зависимости). Да → шаг 3.
  3. Имеет ли агент shell execution или issue/PR editing? Нет - P2A невозможна, проверьте P2S-цепочки. Да → шаг 4.
  4. Есть ли caller identity access control (ограничение allowed_users)? Да - риск ограничен авторизованными пользователями. Нет → шаг 5.
  5. Workflow триггерится на issues.opened или [URL='https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target']pull_request_target[/URL]? Да - критический риск, эксплуатация доступна любому пользователю GitHub. Нет - средний риск, нужны определённые права.
При попадании в категорию критического риска: немедленно ограничьте allowed_users, рассмотрите переход на zero-secret architecture с container isolation. Input sanitization уменьшает attack surface, но не гарантирует защиту - prompt injection работает на семантическом уровне, где regex-фильтры бессильны. Модель не парсит строки - она понимает смысл. И «дополнительная инструкция» для неё неотличима от легитимной.

AWI ставит перед индустрией вопрос, на который пока нет элегантного ответа: как совместить полезность LLM-агентов в CI/CD с тем фактом, что они архитектурно не различают данные и инструкции. TaintAWI и JAW показали масштаб - сотни zero-day, тысячи уязвимых workflow - но это snapshot на сегодня. Количество агентских интеграций растёт: каждый крупный LLM-провайдер выпускает official Action, каждый open source проект стремится автоматизировать triage. Через год сканировать придётся не 13 тысяч workflow, а сотни тысяч.

Мой опыт исследования attack surface LLM-агентов в пайплайнах привёл к неутешительному выводу: текущие mitigation'ы - input sanitization, permission restriction, output validation - каждый по отдельности обходится. Sanitization не спасает, потому что модель оперирует семантикой, а не синтаксисом. Permission restriction уменьшает blast radius, но не устраняет уязвимость. Output validation требует формализации «допустимого» поведения агента, что противоречит самой идее использования LLM для нетривиальных задач.

Единственный архитектурно надёжный подход - zero-trust к агенту: полная изоляция контейнера, zero-secret environment, staged writes с vetting. GitHub движется в этом направлении, но их модель не стала стандартом. Многие команды подключают claude-code-action с дефолтным GITHUB_TOKEN и надеются, что «никто не создаст issue с payload».

Публичные инциденты показывают: AI-агенты уже ищут и эксплуатируют эти workflow автоматически. Гонка атаки и защиты в агентских CI/CD началась. Пока - атакующая сторона адаптируется быстрее. Прогоните свои workflow через decision tree выше. Если дошли до пункта 5 и ответ «да» - у вас та же проблема, что и у тех 496 репозиториев.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab