Skip to content

ci: 信頼コントリビュータ限定の CI 自動承認(fork PR)+外部 fork PR の承認ゲート #426

Description

@shogun-aki-tweak

目的

「push は許可できないが信頼できる fork コントリビュータ」の CI を自動実行しつつ、untrusted な外部 fork PR の CI は承認ゲートで止める、という CI ガバナンスを整える。

背景(GitHub の制約)

GitHub は CI 自動実行の免除を repo の Write 権限に不可分に紐づけている。ゆえに「push は与えないが CI は信頼して自動実行したい」という中間ケースを native には表現できない(Write を与えると push も付く/custom role でも CI 免除は base ロール依存で分離不可)。

また現状の fork PR 承認ポリシーは first_time_contributors初回のみ承認要のため、一度でも貢献した外部者は以降 fork PR の CI が自動実行され、#387 で議論した「untrusted build が pr-number.txt を改竄してコメント偽装」クラスを承認なしに自動発火できてしまう。

設計

1. 承認ポリシーを引き締め

fork-pr-contributor-approvalall_external_contributors に変更(全ての外部 fork PR の CI を Approve and run 待ちに)。これで untrusted 由来の CI は権限層で止まり、#387 の trade-off も権限層で封殺される。

2. 信頼ユーザー限定の自動承認 workflow を追加

  • トリガー = pull_request_target(=base 側の信頼コンテキストで走る。fork コードは実行しない)
  • 権限 = actions: write(+必要な read 系)
  • ロジック:
    1. PR 作者 github.event.pull_request.user.login信頼リストと照合
    2. 該当 → その PR の head SHA で status=action_required(承認待ち)の workflow run を探し、POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve で自動承認
    3. 非該当 → 承認待ちのまま(maintainer が手動承認)

信頼ユーザー = bot が即承認して CI 自動実行/untrusted = 承認ゲート。push は一切与えない。

3. 信頼リストの持ち方(どちらか)

  • (a) base repo のファイル(例 .github/trusted-ci-contributors.yml)— maintainer が PR で編集・追加 token 不要・シンプル
  • (b) Org の Team メンバーシップを API 照合 — 管理は Org UI で楽だが照合に org スコープの token が要る

★安全上の鉄則(pull_request_target ゆえ)

  • 自動承認 workflow は fork のコードを一切 checkout / 実行しない(作者名・信頼リストの照合と approve API 呼び出しのみ)。secret / write token を untrusted コードに触れさせない。
  • 信頼リストは base(信頼側)にのみ置き、fork から改変不能にする。
  • これは ci(frontend): add per-PR bundle size diagnostics (raw/gzip/brotli/zstd) #387 と同じ「信頼境界を越える入力に write を与えない」原則の徹底。

効果

  • 信頼できる外部コントリビュータ(push 権なし)が摩擦なく CI を回せる
  • untrusted 外部 fork PR は承認ゲート(maintainer が実行前に vet)
  • fork PR 由来の攻撃クラス全体ci(frontend): add per-PR bundle size diagnostics (raw/gzip/brotli/zstd) #387 の bundle 診断 trade-off 含む)を権限層で封殺(workflow コード頑健化より広く・強い)

参考

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions