GitHub Actions trust boundary
Release chain надёжна только тогда, когда build identity, permissions, cache behavior и publishing authority разделены и проверяемы.
Коротко: Где возможно, заменяйте reusable publish secrets короткоживущей workload identity. Любой workflow, который может запустить внешний участник, считайте untrusted, включая его cache writes и checkout behavior.

Что изменилось в 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.
Этическая рамка: Примеры являются defensive-конфигурациями. Здесь нет cache-poisoning payloads, secret exfiltration и несанкционированного workflow abuse.