14 июля 2026 года атакующий скомпрометировал релизный пайплайн проекта AsyncAPI, не украв ни одного токена доступа. Вместо этого он воспользовался push-доступом в ветку репозитория и позволил легитимному CI сделать всю грязную работу самостоятельно — включая публикацию вредоносного пакета с валидной SLSA провенанс-атрибуцией.
Как технически работал захват
on:
push:
branches: [next]
permissions:
contents: write
id-token: write
Workflow, реагирующий на push в определённую ветку и обладающий правом на публикацию через OIDC (id-token: write), фактически даёт любому, кто получил push-доступ в эту ветку, возможность инициировать полноценный релиз от имени доверенной инфраструктуры проекта.
Почему провенанс-атрибуция не спасла
Атакующие пакеты несли легитимные SLSA provenance attestations — они честно доказывали, что пакет собран официальным workflow проекта. Провенанс подтверждает происхождение сборки, но не то, что триггерящий коммит был легитимным — если скомпрометирован сам процесс, доверенная подпись на выходе этого процесса ничего не значит.
Практический паттерн риска
| Компонент | Что делает риск реальным |
|---|---|
| Триггер, реагирующий на внешний ввод | pull_request_target, push в ветку с широким доступом |
| Широкие permissions | contents: write, id-token: write, packages: write |
| Отсутствие дополнительных проверок | Нет ручного approval перед реальной публикацией |
Именно сочетание всех трёх факторов создаёт реальную возможность захвата, а не каждый по отдельности.
Практическая защита
Принцип наименьших привилегий — каждый job должен запрашивать только те конкретные права, которые ему реально нужны, а не общий широкий набор permissions на уровне всего workflow. Для действительно критичных релизных пайплайнов разумно добавить ручной approval-шаг перед публикацией, даже если это немного замедляет процесс.
Как проверить собственные workflow на этот паттерн
GitHub Actions Workflow Permissions Batch Auditor проверяет сразу несколько workflow-файлов на именно эту комбинацию риска.
Итоговый чеклист
Захват пайплайна AsyncAPI произошёл без кражи токена — через push-доступ в ветку и избыточные permissions самого workflow.
SLSA provenance подтверждает, что сборку произвёл легитимный процесс, но не то, что запустивший его коммит был легитимным.
Принцип наименьших привилегий на уровне каждого job, а не общие широкие permissions на весь workflow, — практическая защита от этого паттерна атаки.