GitHub Actions の保護強化後も残る「Pwn Request」の経路を潰す
外部 PR のコードを高権限で動かす Pwn Request への新しい保護は、新しい actions/checkout とキャッシュにしか効かない。古い checkout への SHA 固定、自作の git 取得、issue_comment 起点、PR タイトルのシェル埋め込みなどは別に点検する。
何が変わったか
actions/checkoutに外部 PR のコード取得を止める保護が入った(v7.0.0 で導入、v2.8.0・v3.7.0・v4.4.0・v5.1.0・v6.1.0 にも反映)。- 公開リポジトリで
pull_request_targetを止める既定ルールは現在評価モードで、強制適用は 12 月 2 日の予定。対象は、イベントポリシーが設定されていない公開リポジトリ。非公開・内部リポジトリは対象外。
保護が効かない経路(点検リスト)
- 保護導入前の checkout を指す SHA 固定: SHA 固定そのものは正しいが、指しているのが保護前のコミットなら効かない。上の版以降へ固定し直す(GitHub Actions の依存を lockfile(actions.lock)で固定する の
--relockや pinact で更新)。 - 対象外のイベント: 保護の対象は
pull_request_targetと、PR イベントを起点にしたworkflow_run。issue_commentなどのイベントから PR のコードを取ってくる構成は守られない。 - checkout 以外の取得方法: 自作の
git fetch/git clone、第三者のコード取得用アクションは対象外。 - 保護の解除:
allow-unsafe-pr-checkoutを指定している箇所を grep する。 - コードを取らなくても成立するインジェクション:
run:に${{ github.event.pull_request.title }}などを直接埋め込むとシェルインジェクションになる。値はenv:経由で渡し、シェル側でクォートする。 - 低権限ジョブの成果物:
pull_requestで作った artifact をworkflow_runで受け取る構成では、その中身を信用しない(展開先・実行の有無を審査)。 - 使い捨てでないセルフホストランナー: 前の実行のデータが残るランナーは、checkout やキャッシュの保護とは別問題。外部 PR を動かすなら使い捨てにする。
やること
- 既定ルールを待たず、必要なワークフローだけ
pull_request_targetを明示的に許可し、実行者(作成者の関連付け、ラベル承認など)と入力の検証を組み合わせる。 - 非公開・内部リポジトリは 12 月のルールの対象外なので、自分でイベントポリシーを設定する。
- 基本の考え方は pull_request_target とキャッシュポイズニングの危険を潰す を参照。