このガイドは、ワークフローで pull_request_target イベントを使用する必要があるかどうかを評価し、関連するセキュリティ リスクを理解するのに役立ちます。 また、既定でこれらのリスクを軽減するために、actions/checkout v7 以降に適用される保護と、必要に応じてその保護をオプトアウトするタイミングについても説明します。
これらのワークフローのいずれかからプル リクエストのコードをチェックアウトする前、または actions/checkout で allow-unsafe-pr-checkout 入力を設定する前に、pull_request_target を読んでください。
pull_request_targetイベントのリスク
pull_request_targetによってトリガーされるワークフローは、昇格された信頼で実行されます。ジョブは、基本リポジトリのGITHUB_TOKENを受け取り、リポジトリと組織のシークレットにアクセスし、default-branch キャッシュへの書き込みアクセスを受け取ります。 これは、コラボレーターのみがトリガーできる push などのイベントに与えられるのと同じ信頼であり、ラベル付け、トリアージ、認証済み状態チェックの投稿など、フォークからのプル要求に応答する自動化に pull_request_target 役立ちます。
これが既定で安全である理由と、その安全性が一般的にどのように壊れているかを理解するには、pull_requestに対するを確認します。
(pull_requestおよびpull_request_reviewと共に) pull_request_review_comment イベントは通常とは異なっており、pull request のマージ コミットからワークフロー ファイルが実行されます。 フォークから開かれたプル要求の場合、そのコミットは、ベース リポジトリへの書き込みアクセス権を持たないユーザーによって制御されます。 信頼されていないワークフロー コードを安全に実行するために、 GitHub はこれらのイベントを読み取り専用の GITHUB_TOKENに制限し、他のシークレットへのアクセスを保留し、フォーク承認ポリシーを適用してコンピューティングの不正使用を防ぎます。 詳細については、「ワークフローをトリガーするイベント」を参照してください。 既定では、actions/checkout ワークフロー内のpull_requestは pull request のマージ コミットもチェックアウトするため、コードはチェックアウトされ、実行されるワークフローは一貫しています。
pull_request_target では、重要ではあるものの微妙な変更が 1 つあります。つまり、ワークフローと、ref を指定しない後続の actions/checkout 呼び出しは、プル リクエストからではなく、ベース リポジトリの既定のブランチから取得されます。 既定のブランチの信頼されたコードのみが実行されるため、シークレットと読み取り/書き込みトークンを許可しても安全です。 既定では、フォークのコードは実行されません。
ワークフロー作成者がこの既定値をオーバーライドしてフォークのコードを実行すると、リスクが発生します。 開発者は、CI を介してフォークのプル要求を実行pull_request_target、シークレットにアクセスする (プライベート レジストリを必要とするテストを実行するなど) ため、__ を頻繁に選択します。 これを行うには、既定のブランチではなく pull request ヘッドで actions/checkout をポイントします。これは安全ではありません。
# INSECURE. Provided as an example only.
on:
pull_request_target:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: GitHub
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Test
run: make test
チェックアウト手順だけでは、信頼されていないコードは実行されません。 ワークフロー ファイル自体は、引き続き既定のブランチから取得されます。 この脆弱性は、現在の作業ディレクトリにチェックアウトされたコードを実行する 次 の手順で完了します。 ここでは、make test はプルリクエストのヘッドから取得した Makefile を実行します。 攻撃者は、 Makefile (またはビルド スクリプト、テスト コマンド、依存関係、または構成ファイル) に悪意のあるコマンドが含まれているフォークからのプル要求のみを開く必要があります。 これらのコマンドは、ベース リポジトリのシークレットとトークンを使用して実行されます。
このパターンは "pwn 要求" と呼ばれ、複数のサプライ チェーン侵害の根本原因となっています。 詳細については、からの actions/checkout@v6を参照してください。 脆弱な一般的な図形は次のとおりです。
actions/checkout(ref: ${{ github.event.pull_request.head.sha }}、ref: refs/pull/${{ github.event.pull_request.number }}/merge) でプルリクエストのヘッドコミットまたはマージコミットをチェックアウトしてから、その結果をビルド、テスト、またはその他の処理を実行すること。- フォーク (
repository:) にrepository: ${{ github.event.pull_request.head.repo.full_name }}を設定して、フォークの分岐を直接プルします。 actions/checkoutの外部でプルリクエストのコードを取得し(たとえば、git fetch、gh pr checkoutを使用するか、フォークのpull_request実行で生成されたアーティファクトをダウンロードして)、その後実行します。
Pwn 要求も pull_request_targetに固有ではありません。 シークレットを使用して実行されるイベントは、信頼されていないコードをチェックアウトまたはダウンロードして実行する場合に pwn 要求を発生させることができます。 たとえば、フォークのプル要求コードをフェッチして実行する issue_comment または workflow_run ワークフローは、同様に脆弱です。
workflow_run ワークフローは、他のワークフローによってアップロードされた成果物を信頼されていないデータとして扱う必要があります。その内容はフォークから取得される可能性があるためです。
pull_request_targetを使用するかどうかを決定する
一部のワークフローでは、より高い信頼レベルでフォークされた pull request のコードをチェックアウトする必要があり、そのためにそもそも pull_request_target が作成されました。 たとえば、プライベート成果物レジストリを必要とするカバレッジ レポートを生成したり、pull request から導入された変更に対して認証済みチェックを生成して実行したりします。
pull_request_targetを使用する前に、または allow-unsafe-pr-checkout で actions/checkout フラグを選択する前に、以下の質問を検討してください。
-
代わりに
pull_requestを使用できますか?pull_requestは、pull_request_targetと同じイベントに対してトリガーされ、pull_requestマージ ブランチからワークフロー コードを実行します。 これは、上記で説明した保護機能により、フォークから送られたプルリクエストに対しても安全に実行されます。 追加のシークレット アクセスが必要ない場合は、pull_requestを使用します。 より複雑なワークフローを再構築して、プル要求コードの潜在的に危険な処理とシークレットへのアクセスを分離できます。 詳細については、からの GitHub Security Labを参照してください。 -
チェックアウトされたコードは実行されていますか? これは、pwn 要求の脆弱性が発生する欠陥です。 これは、作業ディレクトリにプル要求ヘッドをチェックアウトしてから実行することで、
actions/checkoutで最も一般的に導入されます。path入力が設定されていない限り、actions/checkoutはコードを$GITHUB_WORKSPACEディレクトリに書き込みます。これは通常、後続のコマンドが実行される作業ディレクトリです。 実行は、独自の手順に限定されるものではなく、npm installやnpm run buildなどのコマンドのビルドとテスト、およびコードによってもたらされる構成ファイルと依存関係によって、攻撃者が制御するコードをすべて実行できます。 実行には明確なビルド ステップは必要ありません。 チェックアウトされたコードがデータとしてのみ検査され、pull_request_targetイベントを使用する前に実行されないようにする必要があります。
pull_request_target ワークフローの強化
pull_request_targetが必要であることを確認した場合は、これらのコントロールを適用して、この危険度の高いイベントの影響を制限します。 これらは、ワークフローがプル要求コードをチェックアウトするかどうかに適用されます。
-
シークレットを制限します。
GITHUB_TOKENに設定されたアクセス許可に最小限の特権があること、およびワークフローに必要なリポジトリと組織のシークレットのみが使用されていることを確認します。 詳細については、「ワークフローでの認証に GITHUB_TOKEN を使用する」を参照してください。 -
キャッシュへの影響について理解します。
GITHUB_TOKENおよび構成されたシークレットの外部では、pull_request_targetで実行されるワークフローは、既定のブランチ上の他のワークフローと共有されているキャッシュへの書き込みアクセス権も持っています。pull_request_targetイベントからこのキャッシュに対する悪意のある変更は、関連のない他のワークフローの実行に影響する可能性があります。 -
基になるコンピューティングが分離され、一時的であることを確認します。 セルフホステッド ランナーを使用する場合は、ランナー環境が内部リソースから適切に制限されており、 GitHub Security Lab 実行間で再利用されていないことを確認する必要があります。 詳細については、「セキュリティで保護された使用に関するリファレンス」を参照してください。
-
ゲートは承認後に実行されます。
pull_request_targetワークフローは、書き込み権限を持つユーザーのみが追加できる必須のlabelを条件として制限できます。 これについては、GitHub Actionsするガイドで詳しく説明します。 -
GitHub Actionsセキュリティのベスト プラクティスを適用します。 pwn 要求の特定のリスクに加えて、コマンドインジェクションなどの他の一般的な脆弱性が存在し、この特権イベントで実行されるコードに影響を与える可能性があります。 詳細については、「GitHub Security Lab」を参照してください。 一般的なGitHub Actionsの脆弱性を特定して予防的に保護するには、CodeQLのGitHub Actionsを有効にします。 詳細については、「コード スキャンの既定セットアップの構成」を参照してください。
組み込みの保護機能を無効にする
上記の質問に取り組み、ワークフローに pull_request_target が必要であり、安全に使用されていることを確認した場合は、 actions/checkout 保護をオプトアウトできます。
allow-unsafe-pr-checkout: trueをactions/checkout入力として指定すると、フォークの pull request の head ref をチェックアウトできるようになります。 チェックアウトされたコードが実行されていないことを確認した後でのみ、これを行います。 入力は意図的にコード レビューと静的分析で見つけやすいように名前が付けられています。
この保護は、フォークされた pull request 参照のみを対象とします。 関連のないサードパーティリポジトリ、 git fetch または gh pr checkoutを使用したコードのフェッチ、ダウンロードした成果物の実行など、他の信頼されていないコードのチェックアウトは、 actions/checkout チェックの対象になりません。
pull_request_targetの使用を制限する
リポジトリ、組織、エンタープライズ管理者は、ワークフロー実行保護を使用して、ワークフローをトリガーできるイベントとアクターを制御できます。 リポジトリに pull_request_targetの正当な使用がない場合、それを制限すると、個々のワークフローの書き込み方法に関係なくリスクが排除されます。