Что изменилось в defensive-модели
GitHub усиливает границы Actions: untrusted triggers получают read-only cache в опасных shared contexts, а checkout для pull_request_target становится безопаснее по умолчанию. Эти platform controls снижают типовые privilege-escalation paths, но не чинят небезопасные custom scripts и избыточные permissions.
Не менее важен общий supply-chain вектор: OIDC и trusted publishing позволяют registry доверять identity workflow, а не статическому токену в repository secrets.
Вопросы для аудита
- Какие события запускают workflow и может ли внешний contributor влиять на исполняемый код или аргументы?
- Получает ли job ненужные id-token, contents write, packages write или environment secrets?
- Может ли untrusted job записать cache или artifact, который позже использует trusted release job?
- Закреплены ли actions на immutable commits и проверяются ли runner images и permissions?
- Использует ли публикация short-lived identity, provenance и environment approval boundary?
Безопасный фрагмент workflow
Минимальный publishing skeleton: default read-only permissions и OIDC только для publish job. Конкретные registry steps зависят от экосистемы.
name: release
on:
push:
tags: ["v*"]
permissions:
contents: read
jobs:
publish:
environment: production-release
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@PINNED_COMMIT_SHA
- run: npm ci --ignore-scripts
- run: npm test
# Registry-specific trusted publishing follows here.
# No long-lived publish token is stored in repository secrets.
Evidence и retest
- Экспортировать effective workflow permissions и определить каждый secret-bearing job.
- Доказать, что fork или другой untrusted trigger не может писать shared trusted cache state.
- Проверить provenance опубликованного пакета и identity workflow, который его создал.
- Провести retest emergency release path, где чаще всего остаются static credentials.