GitHub Actionsのpull_request_targetは12月2日から既定でブロック|11月9日の試験停止までに対象を探して対応を決める

GitHubが公開リポジトリのpull_request_targetを12月2日から既定で止める

GitHubは2026年11月2日、GitHub Actionsの pull_request_target を公開リポジトリで既定でブロックすると告知しました。開始は2026年12月2日で、もともと予定していた11月2日から1か月延びています。本番のブロックの前に、11月9日と11月16日に2時間ずつ試験的に止める時間帯も設けられました。

pull_request_target は、フォークから届くものを含むプルリクエストに反応して動く、ワークフローのきっかけ(イベント)です。ラベルを自動で付ける、プルリクエストにコメントするといった自動化でよく使われます。同じリポジトリ内のプルリクエストでも動きます。公開リポジトリでこのイベントを使っていると、リポジトリや組織に適用されるイベントポリシー(どのイベントでワークフローを動かしてよいかを決める設定)がない限り、12月2日以降は実行が失敗し、中身は動かなくなります。

この記事では、GitHubの告知と公式ドキュメントをもとに、影響する条件と日程を整理します。あわせて、9種類のサンプルで対象の探し方を手元で比べ、残す、置き換える、直すのどれを選ぶかの判断をまとめました。公開リポジトリでGitHub Actionsを使っている人に向けた内容です。

3分で把握

試験停止(日本時間11月10日未明)までに、pull_request_targetを使うワークフローを洗い出す

GitHubの2026年11月2日の告知と、手元のサンプルでの比較をまとめました。

影響するリポジトリ

公開リポジトリ

Free、Team、Enterprise Cloudが対象です。非公開、社内向け、Enterprise Serverは対象外です。

止まる単位

イベントごと

ラベル付けだけの安全なワークフローも、許可しなければ止まります。

探し方

on: をYAMLとして読む

9種類のサンプルのうちブロックされる7件を、YAMLとして読む方法はすべて見つけ、誤検出もありませんでした。

12月2日までに2回、試験停止の時間帯がある

12月2日の前に動作を確かめる機会が2回あります。試験停止の時間帯には、ブロックの対象になる実行が失敗扱いになり、エラーの注記が付いて、ワークフローの中身は動きません。時間帯が終わると、警告だけを出して実行を続ける状態に戻ります。

現在:評価モード。実行は続き、Policy insightsの画面でブロックされる予定の実行を確認できます。

11月9日 16:00〜18:00(UTC):1回目の試験停止。日本時間では11月10日の1:00〜3:00です。

11月16日 16:00〜18:00(UTC):2回目の試験停止。日本時間では11月17日の1:00〜3:00です。

12月2日:既定のブロックが常時有効になります。

日本時間では深夜にあたるので、普段の作業中に試験停止の失敗を目にすることは少なそうです。夜間にプルリクエストを受ける公開リポジトリでは、この時間帯の失敗はブロックが原因の可能性があります。Policy insightsは、リポジトリのSettingsのサイドバーで、ActionsのPoliciesのすぐ下に並ぶページです。

GitHubが止めるのは、フォークのコードを動かす事故を防ぐため

pull_request_target のワークフローには、リポジトリのシークレットと書き込みできる GITHUB_TOKEN が渡されます。何も指定しなければ、動くのは既定ブランチのコードで、プルリクエスト側のコードは動きません。

危険になるのは、次のようにプルリクエスト側のコードを取り出して動かすときです。攻撃者がフォークで Makefile を書き換えてプルリクエストを送るだけで、そのコマンドがシークレット付きで動きます。GitHubはこの形を「pwn request」と呼び、複数のサプライチェーン攻撃の原因になったと説明しています。

on: pull_request_target
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.3                   # 取り出しを拒否する機能が入る前の版
        with:
          ref: ${{ github.event.pull_request.head.sha }}  # フォーク側のコード
      - run: make test                                    # それを実行してしまう

現在の actions/checkout はこの取り出しを既定で拒否します(後述)が、古い版に固定している場合や、別の方法でコードを取り出す場合は危険が残ります。今回のブロックは、この形かどうかを見分けません。イベントの名前で判定するので、コードを取り出さないラベル付けのワークフローも同じように止まります。安全に使っている人ほど、影響に気づかない可能性があります。

対象を探すなら、on:をYAMLとして読む方法が確実

影響するワークフローの探し方を3通り用意し、9種類のサンプルで比べました。文字列を探す grep、YAMLとして on: を読む短いスクリプト、ワークフロー専用の検査ツール zizmor 1.32.0 の dangerous-triggers です。

サンプルの書き方grepon:をYAMLで読むzizmorのdangerous-triggers12月2日以降
on: pull_request_target検出検出検出止まる
on: [push, pull_request_target]検出検出検出止まる(pushでの実行は続く)
on: の下の行に書き、actions/labelerの1ステップだけを使う検出検出検出なし止まる
"on": のように引用符付きで書く検出検出検出止まる
コメントに名前が残るだけ(実際は pull_request)誤検出検出なし検出なし止まらない
pull_request で make test検出なし検出なし検出なし止まらない
head.sha を取り出して make test検出検出検出止まる
1つ上の行の例に allow-unsafe-pr-checkout: true(取り出しの拒否を解除する設定)などを足す検出検出検出止まる
gh pr checkout で取り出して ./build.sh検出検出検出止まる

macOS 27、zizmor 1.32.0で2026年11月4日に確認。「12月2日以降」は、公開リポジトリで独自のイベントポリシーがない場合について、GitHubの説明から筆者が判断した列です。

grep はすべて拾えますが、コメントに名前が残るだけのファイルも拾います。zizmorは actions/labeler の1ステップだけのワークフローに dangerous-triggers を出しませんでした。ステップを run に変えると検出され、actions/labeler に戻すと消えます。一方で、echo だけのワークフローと、プルリクエストのコードを動かすワークフローには同じ指摘が出ます。そのため dangerous-triggers の有無だけでは、ブロックの対象を数えることも、危険度を分けることもできません。棚卸しは on: を読む方法で行い、危険かどうかはワークフローの中身を読んで判断します。

最初の棚卸しには、次のスクリプトが使えます。YAML 1.1では on が真偽値の true として読まれるので、その両方を見ています。リポジトリのルートで実行すると、対象のファイル名だけが出ます。

# find_prt.py(uv run --with pyyaml python find_prt.py .)
import sys, pathlib, yaml
for p in sorted(pathlib.Path(sys.argv[1]).glob('.github/workflows/*.y*ml')):
    d = yaml.safe_load(p.read_text()) or {}
    on = d.get('on', d.get(True))
    names = [on] if isinstance(on, str) else list(on or [])
    if 'pull_request_target' in names:
        print(p.name)

リポジトリが多い場合は、GitHubのコード検索でまとめて候補を出してから、個別に確かめます。OWNER は自分のアカウントか組織の名前に置き換えてください。件数の既定の上限は30件なので --limit を付けます。自分が読める非公開リポジトリも結果に混ざるので、公開リポジトリだけに絞って確かめます。

gh search code "pull_request_target path:.github/workflows" --owner OWNER --limit 1000

見つけたワークフローは3つの対応に分かれる

対象が見つかったら、ワークフローが何をしているかで対応を決めます。GitHubの説明をもとに、3つに分けました。

シークレットも書き込み権限も不要なら:pull_request に置き換える

テストの実行などは pull_request へ移せます。フォークからのプルリクエストでは、トークンが読み取り専用になり、シークレットも渡されません。動くワークフローがプルリクエスト側のものに変わり、コンフリクトがあると動かず、初めての投稿者には承認が必要な場合があります。

書き込みが必要でコードは動かさないなら:ポリシーで許可して残す

ラベル付けやコメントのように、フォークのコードを動かさないワークフローです。イベントポリシーで pull_request_target を許可し、権限を必要な分だけに絞ります。プルリクエストのタイトルなどを run に直接埋め込んでいないことも確かめます。

シークレットや書き込みできるトークンを持たせたまま、プルリクエストのコードを動かしているなら:作り直す

ブロックを待たずに直す対象です。コードを動かす処理と、シークレットや書き込み権限を使う処理を分けます。npm install や設定ファイルの読み込みも、コードを動かす処理として数えます。

リポジトリ、組織、Enterpriseのいずれかに適用されるイベントポリシーがすでにあれば、GitHubの説明では既定のブロックに置き換わりません。その場合は、そのポリシーが pull_request_target を許可しているかを先に確かめます。新しく許可するときは対象を絞ります。リポジトリのSettingsにあるActionsのPoliciesで作り、対象のワークフローのファイルを指定して、Restrict eventsで許可するイベントを選びます。GitHubはこの設定を許可リストと説明しているので、そのワークフローが使う他のイベント(push など)も一緒に選びます。作成後は、指定したワークフローと他のワークフローがそれぞれどう判定されるかをPolicy insightsで確かめます。使っていないワークフローなら、ポリシーを作らずファイルごと削除すれば、失敗の記録も残りません。

actions/checkoutはフォークのコードの取り出しを既定で拒否する

ポリシーで許可しても、actions/checkout の拒否で止まることがあります。2026年6月に公開されたv7から、pull_request_target などのワークフローでフォークのコードを取り出そうとするとエラーになりました。この動作は7月に古いメジャー版へも入っています。ソースコードを読むと、取り出すリポジトリがフォークのとき、参照が refs/pull/… の形のとき、コミットがプルリクエストのものと一致するときに拒否する作りです。

取り出しを続けるには allow-unsafe-pr-checkout: true を明示します。GitHubは、取り出したコードを実行しないと確かめてから使うよう求めています。@v6 や @v4 のようにメジャー版のタグで指定していれば、この拒否はすでに働きます。手元で各タグの設定ファイルを読むと、v6 と v4 には設定項目があり、v6.0.3 にはありませんでした。古いパッチ版やコミットのSHAに固定しているなら、更新を検討します。

この拒否は actions/checkout の中だけで働きます。先ほどの表にある gh pr checkout や、run の中の git fetch でコードを取り出す形には働かないので、ワークフローを読むときは run の中身も確かめます。

11月9日までにやっておく4つのこと

  1. 公開リポジトリで上のスクリプトかコード検索を使い、pull_request_target を使うワークフローを一覧にする。
  2. Policy insightsの画面で、ブロックされる予定の実行と一覧を見比べる。
  3. 各ワークフローを、置き換える、許可して残す、作り直すのどれかに分ける。
  4. 許可して残すものはポリシーを作り、日本時間11月10日1:00〜3:00の試験停止の間にテスト用のプルリクエストを開いて、実行履歴で動いたかを確かめる。

私なら、ラベル付けのような小さなワークフローから順にポリシーを作ります。止まっても被害の小さいものを1回目の試験停止で試しておくと、2回目までに残りの判断に時間を使えます。

参考資料