validate-pr-review-action で Pull Request の review を validation
以前、自分で Pull Request にコミットを push して approve する self approve を防ぐ方法を考察し、 CLI ツールと GitHub Action を作って記事を書きました。
今回はその内容を発展させ、新たに開発した GitHub Action を紹介します。
Validate PR Review Action は pull request の review を validation する action です。
Pull Request をマージする前に pull_request_review
event で実行して validation します。
この action を実行する job を Branch Rulesets の Required Checks に追加することで、 validation が通らない限りマージできないようにします。
name: Validate pull request reviews
on:
pull_request_review:
types:
- submitted
- dismissed
jobs:
validate-pr-review:
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
pull-requests: read # To get pull requests
contents: read # To get pull request commits
steps:
- uses: suzuki-shunsuke/validate-pr-review-action@bd967a12742566a5e3fb02878e4e2447da68f72e # v0.0.4
validate-pr-review-action は GitHub GraphQL API で pull request の author, commits, reviews などを取得し、以下のようなバリデーションを行います。
- PR の最新の commit に対して PR に commit している人以外が approve していなければなりません
- 古い commit への approve は無視します
- PR の committer の approve は無視します
- GitHub App や信頼できない Machine User による approve は無視します
- 不正に approve している可能性があるため
- 以下の場合、 2 人以上が approve していなければなりません
- 信頼できない Machine User や GitHub App が commit している場合
- 信頼できない Machine User などを悪用して commit して自分で approve している可能性があるため
- PR の作成者が信頼できない Machine User や GitHub App の場合
- 信頼できない Machine User などを悪用して PR を作成して自分で approve している可能性があるため
- GitHub User に紐づかない commit が含まれる場合
- User を誤魔化して自分で commit して approve している可能性があるため
- 信頼できない Machine User や GitHub App が commit している場合
これらの validation により、先述の記事で挙げた 3 つのパターン全てに対応できていることになります。
- codeowner 権限を持つ Machine User を悪用して approve => PR できない Machine User の approve は無視
- 自分以外が作成した PR に自分で commit を追加して自分で approve => PR の committer の approve は無視
- 自分以外が作成した PR に Machine User や bot で commit を追加して自分で approve => 信頼できない Machine User や GitHub App が commit している場合、 2 approve を要求
Branch Rulesets で Commit Signing を必須にする
Branch Rulesets で Commit Signing を必須にしましょう。
そうでないと、他の人になりすまして commit をして自分で approve することができてしまいます。
Branch Rulesets で必須にすることができるため、 validate-pr-review-action は commit signing によるバリデーションは行いません。
信頼できる GitHub App と信頼できる(ない) Machine User
action の input で信頼できる GitHub App と信頼できる(ない) Machine User のリストを指定することができます。
- uses: suzuki-shunsuke/validate-pr-review-action@bd967a12742566a5e3fb02878e4e2447da68f72e # v0.0.4
with:
trusted_apps: |
renovate
dependabot
trusted_machine_users: |
suzuki-shunsuke-bot
untrusted_machine_users: |
mini-core
/-bot$/
untrusted_machine_users
では正規表現が使えますが、 trusted_apps
と trusted_machine_users
では使えません。
これは正規表現で意図せず GitHub App や Machine User を信頼できるものとして扱わないようにするためです。
正規表現を使う際は /-bot$/
のように正規表現を /
で囲います。
trusted_machine_users
は untrused_machine_users
の正規表現にマッチする一部のユーザーを除外するのに使うことを想定しています。
ある GitHub App が信頼できるかどうか、ある User が信頼できない Machine User であるかどうかは、それらが適切に管理されているか、悪用できる状態にあるかによって決まります。
例えばある GitHub App が Organization の全リポジトリにインストールされていて contents:write や pull_requests:write 権限を持っていて App ID や Private Key が Organization Variables と Organization Secrets で全リポジトリに共有されているような場合、その GitHub App は信頼できません。
Organization のメンバーであれば誰でも任意のリポジトリの任意のブランチからその GitHub App を悪用して PR や commit を作成したり PR を approve したりすることができるからです。
デフォルトでは renovate
と dependabot
は信頼できる GitHub App とし、それ以外は信頼できない GitHub App とします。
当然ですが、適切に管理されていない GitHub App を trusted_apps
に追加するのはやめましょう。
Machine User については、一部の信頼できる Machine User を除き、全ての Machine User を信頼できないものとして指定しましょう。
GitHub App や Machine User の適切な管理
どのように管理すれば適切に管理されていると言えるでしょう?
人・組織によって基準は異なるかと思いますが、以下のような点が挙げられます。
- 組織内で PAT や Private Key が広く知られていない
- 不特定多数のメンバーに知られている場合、適切に管理されているとは言えません。 revoke するべきでしょう
- Rulesets によって適切に保護された branch や tag で実行される workflow からのみ Personal Access Token や Private Key が参照できるようにします
- GitHub Environment Secrets で保護したり、 AWS Secrets Manager や Google Secret Manager のような secret manager で管理して OIDC で repository や branch, tag, workflow によってアクセスを制限する必要があります
- それらの workflow の変更は validate-pr-review-action によって review が必須になっている必要があります
Client/Server Model Action
feature branch など、適切に保護された branch 以外で GitHub App や Machine User を使いたいケースは当然あります。
その場合、 Client/Server Model Actions (以下 CSM Actions) が役に立ちます。
CSM Actions で現状実装されている action の種類は多くありませんが、以下のようなセキュリティ的に重要な action がサポートされています。
- PR のコード修正: https://github.com/csm-actions/securefix-action
- PR branch の update: https://github.com/csm-actions/update-branch-action
- Machine User による PR の approve: https://github.com/csm-actions/approve-pr-action
下記の記事で紹介した Securefix Action も csm-actions に移動しました。
セキュアな PR branch の update
validate-pr-review-action は PR の committer の approve を無視します。
これは review を強制するために必要ですが、 reviewer が PR の update branch をしてしまうと、その人以外が approve しないといけなくなるという欠点もあります。
実際、 reviewer が update branch したくなるケースはままあります。
そこで、 CSM Actions の Update Branch Action を使うと Client/Server Model でセキュアに update branch することができます。
Discussion