
Воспроизводимые уязвимые и исправленные фикстуры GitHub Actions для инъекций в агентные рабочие процессы (CVE-2026-44246) с измеренным покрытием детекторов и рекомендациями по устранению.
Воспроизводимые уязвимые/исправленные фикстуры для класса ошибок, опубликованного как CVE-2026-44246 (nnU-Net, инъекция в агентный рабочий процесс, CVSS 7.2, CWE-1427), а также измеренный вывод трёх детекторов на них.
Он существует потому, что не с чем было тестировать детектор. Написание правила для этого класса означает написание фикстуры вручную и надежду на её точность; опубликованные ревизии были доступны только при знании, на какой коммит смотреть, что и оказалось самой интересной частью.
Рабочий процесс GitHub Actions передаёт недоверенный текст ИИ-агенту, у которого есть учётные данные репозитория.
Четыре условия, все необходимые:
issues, issue_comment, pull_request_review —
события, текст которых может создать любой, у кого есть учётная запись GitHub.issues: write, contents: write и так далее.claude-code-action и
codex-action отклоняют актора запуска без права записи, если только входной
параметр (allowed_non_write_users, allow-users) явно не разрешит его. Без
этого параметра недоверенный автор никогда не достигает агента, и рабочий процесс
является безопасной конфигурацией, а не этой.${{ github.event.issue.body }} внутри prompt:), либо полученный во время
выполнения (gh issue view) с токеном, который передаёт задание.Это не инъекция шаблона. Ничего не вычисляется как shell; полезная нагрузка — это
проза, а интерпретатор — модель. Именно поэтому обычный совет — заключайте переменные
в кавычки, не используйте eval — не применим, и поэтому исправление ниже касается
того, чего агент может достичь, а не экранирования ввода.
nnU-Net усилил этот рабочий процесс в двух коммитах, и детектор, который рассматривает «до» и «после» как бинарные состояния, ошибается на среднем.
| ревизия | коммит | дата | --allowedTools агента | вердикт |
|---|---|---|---|---|
| уязвимая | 94300b49e716 | 2026-04-13 | gh issue comment, gh issue edit | достижимая запись |
| «исправление» | 4e4770b0b0e6 | 2026-04-24 | только gh issue comment; маркировка перенесена в скрипт-обёртку | всё ещё достижимая запись |
| поздняя | 11bd8746fc06 | 2026-04-27 | ни то, ни другое; более поздний шаг публикует из файла, который пишет агент | недостижимо |
Коммит, который все назвали бы исправлением — его сообщение «hardened issue
and PR agents» — удалил gh issue edit и направил метки через
.github/scripts/safe-label.sh, но оставил Bash(gh issue comment:*) у
агента. Агента всё ещё можно было склонить к комментированию, а шаблон
разрешённого списка gh issue comment:* не ограничен триггерным issue, поэтому
цель выбирала модель. Только третий коммит закрыл это: теперь агент
пишет /tmp/issue-comment.md, а более поздний, не-агентный шаг публикует его с
ISSUE: ${{ github.event.issue.number }}, взятым из события.
Отсюда следуют две вещи, и именно поэтому этот репозиторий — не просто два файла:
«Исправлено» — это утверждение о ревизии, а не о версии. v2.4.1 упоминается как
исправленный релиз, но его .github/workflows/ содержит только codespell.yml —
агентных рабочих процессов в этом теге вообще нет. Вы не можете проверить исправление
по тегу; нужно закрепить коммит.
Блок permissions никогда не меняется. issues: write присутствует и корректен
во всех трёх ревизиях, включая последнюю, потому что он нужен более позднему шагу.
Детектор, который опирается только на permissions, не может отделить ревизию 1 от
ревизии 3. Их разделяет то, что может вызвать агент.
Три детектора, запущенные на обеих фикстурах и всех трёх реальных ревизиях. Полный сырой вывод и версии инструментов в results.md.
| ревизия | agentbound 0.1.3 | sisakulint v0.3.7 | zizmor 1.30.1 |
|---|---|---|---|
1-vulnerable | HIGH write-scope, HIGH untrusted-content | ai-action-prompt-injection | — |
2-fix-commit | HIGH write-scope, CRITICAL author-association | — (только generic) | — |
3-later | LOW write-scope, CRITICAL author-association | ai-action-excessive-tools, ai-action-execution-order | — |
Ни один детектор здесь не является просто «неправильным» — они отвечают на разные вопросы:
ai-action-prompt-injection срабатывает на уязвимой ревизии, где тело issue
интерполируется в prompt:, и перестаёт срабатывать, как только интерполяция
исчезает. Верно. Его находки на поздней ревизии стоит прочитать, прежде чем
действовать по ним — ai-action-excessive-tools отмечает Write, который этот
рабочий процесс использует намеренно, чтобы записать файл, который публикует
более поздний шаг; а ai-action-execution-order хочет, чтобы агент был последним,
чего этот дизайн как раз избегает, поскольку привилегированные шаги идут после
завершения хода модели.permissions задания. Его
находка ci-agent-missing-author-association сообщается как critical на
поздней ревизии, и его собственный README описывает это как чрезмерно строгое, а
не ложное: auto-triage предназначен быть достижимым для кого угодно.У каждого инструмента здесь есть находка, которую он сообщает на ревизии, автор которой уже рассуждал об этом самом условии. Это нормальное состояние эвристики, и причина, по которой таблица покрытия полезнее столбца pass/fail.
git clone https://github.com/sushant-me/agentic-workflow-injection
cd agentic-workflow-injection
bash scripts/fetch-revisions.sh # три реальные ревизии, закреплённые по SHA
bash scripts/benchmark.sh # запускает каждый установленный детектор
benchmark.sh сообщает об отсутствующем детекторе как об отсутствующем, а не
пропускает его молча, потому что таблица покрытия, которая тихо опускает инструмент,
ничего о нём не доказывает.
Фикстуры — это сокращённая форма, написанная для этого репозитория и лицензированная
под MIT, как и всё остальное. Они механизм-точные, а не копии:
fixtures/vulnerable.yml содержит четыре условия и ничего больше, а
fixtures/fixed.yml — тот же файл с шестью изменениями, которые имеют значение,
каждое аннотировано. Если вы добавляете правило, эти два файла — минимальные входные
данные, которые оно должно обработать правильно.
Две особенности интерфейса, обрабатываемые в скрипте, но о которых стоит знать:
not found и завершается с кодом 3. Без присмотра это выглядит
идентично чистому сканированию.path у agentbound — это basename, поэтому сканирование каталога по файлам
с одинаковым именем неоднозначно.Обнаружение — это лёгкая половина. docs/mitigations.md охватывает другую половину: как ограничить полномочия агента, со слоями, ранжированными по одному вопросу — зависит ли этот контроль от того, что модель решит подчиниться?
Это ранжирование — весь смысл. Инструкция в промпте — это ввод, а не защитное условие; шаблон инструмента, который называет свою цель, или токен, которого у агента никогда нет, — это ограничение. Руководство идёт сверху вниз от «модель не может сделать неправильное» до «модель попросили не делать», с контрольным списком и эволюцией nnU-Net в качестве разобранного примера.
fixtures/fixed.yml помечает каждое из своих шести изменений слоем, который оно
реализует, и тем, является ли оно несущим — два из них не являются, и помечены
так, чтобы читатель не переоценил файл.
Получено во время выполнения по SHA коммита, никогда не вендорится:
| файл | репозиторий | коммит | путь |
|---|---|---|---|
real/1-vulnerable.yml | MIC-DKFZ/nnUNet | 94300b49e716 | .github/workflows/issue-triage.yml |
real/2-fix-commit.yml | MIC-DKFZ/nnUNet | 4e4770b0b0e6 | .github/workflows/issue-agent.yml |
real/3-later.yml | MIC-DKFZ/nnUNet | 11bd8746fc06 | .github/workflows/issue-agent.yml |
Никакая копия конфигурации nnU-Net здесь не распространяется; повторно запустите получение и сравните байты сами с блобами выше.
Это артефакт инженерии обнаружения. Он не содержит эксплойта, и ничто здесь не
тестировалось на живом рабочем процессе — уязвимые ревизии являются статическими
файлами, уже публичными в истории nnU-Net и упомянутыми в опубликованном
рекомендательном бюллетене. Фикстуры помечены do not deploy, потому что они
существуют, чтобы быть обнаруженными, а не скопированными.
Если вы поддерживаете детектор для этого класса и хотите строку в таблице,
скрипт бенчмарка — это интерфейс: добавьте раздел, который запускает ваш инструмент
по targets и печатает его находки, а фикстуры и закреплённые ревизии сделают
остальное.
MIT.