forkからのPull RequestだけCIが失敗し、同じ変更を本体repositoryで動かすと成功する。そんなとき、secretの登録場所を増やす前に、どのイベントがどのコードを実行しているか確認します。fork PRでsecretが渡らないことは、設定漏れとは限りません。信頼していない変更を認証情報から分けるための境界が関係します。
この記事では、PRのテストを続けたい保守担当者が、secretなしで実行できる検証と、信頼済みの処理だけに任せる作業を分ける手順を扱います。OIDC tokenの発行やcloud側trust policyの診断は別の問題です。
目次
最初に成功runと失敗runの条件を並べる
ログにsecret値を表示して有無を調べてはいけません。イベント名、PRの送信元repository、workflowの参照元、失敗step、必要な認証先を記録します。空文字や認証エラーだけから「secretが存在しない」と結論づけず、そのrunへ提供される条件を見ます。
表は横にスクロールできます
| 確認項目 | 比較する内容 | 分かること |
|---|---|---|
| イベント | pull_request、push、pull_request_target等 | 実行の信頼境界が同じか |
| PR送信元 | 本体のbranchかforkか | 外部変更を扱う経路か |
| 実行するコード | base側、PRのhead、merge commit | secretを使う処理へ外部変更が混ざるか |
| 失敗step | private registry、API、通知等 | secretが必要な作業を限定できるか |
| 利用環境 | public/private、組織のActions設定 | 適用されるポリシーを確認する先 |
GitHubのイベント資料では、fork由来のpull_requestでは通常GITHUB_TOKEN以外のsecretをrunnerへ渡さず、GITHUB_TOKENの権限も制限すると説明しています。private repository等のfork設定では扱いを変えられる場合があるため、一般的な既定動作と自分の組織の設定を混同しないでください。GitHub:Events that trigger workflows(新しいタブで開く)
runの実行承認と、secretを提供する設定は別に確認します。「承認されたから通常のpushと同じcredentialが使える」と読み替えないことが大切です。
secretを必要とする作業を小さく分ける
例えば、公開依存関係だけで行う構文検査と、private registryへ接続する結合テストでは、必要な認証が違います。CI全体を「secretがないと何もできない」と扱わず、失敗stepから入力と権限を分解します。以下は設計を考える架空例で、実行確認済みの構成ではありません。
表は横にスクロールできます
| 作業 | fork PRでの検討 | 残す確認 |
|---|---|---|
| 公開依存だけの構文・単体検査 | secretなしで実行できる範囲を切り出す | install scriptや実行環境の安全性 |
| private依存が必要な検査 | 代替fixtureや信頼済み経路を検討 | 省略した検査と、後で実行する条件 |
| label・triage等の管理処理 | base側の信頼済み処理で扱う | 必要最小のtoken権限と入力の扱い |
| 公開・配布・本番接続 | PRの検証と別の信頼境界で扱う | 対象commit、実行者、承認・復旧条件 |
secretをダミー値に置き換えて検査を通す場合も、実際の結合テストと同じ保証にはなりません。PR上で「単体検査は完了、private接続検査は未実施」と区別し、未実施の確認がどの段階で必要かを残します。失敗を見えなくするために無条件成功へ変えると、必要な検証が実行されたか分からなくなります。
pull_request_targetへ変える前にコードの実行元を見る
pull_request_targetは、fork PRに対するlabel付けなど、base側の権限を使う管理処理で検討されるイベントです。しかし、secretを使えるようにするだけの置換先ではありません。GitHubは、base側の権限を持つrunで外部PRのコードを取得し、そのコードをbuild・test等で実行する構成を危険な形として説明しています。GitHub:Securely using pull_request_target(新しいタブで開く)
checkout自体だけでなく、その後に実行するMakefile、package script、依存関係、設定ファイルまで追います。見た目は固定された「テスト実行」でも、読み込む内容がPRで変更できれば、その変更が認証情報へ到達する経路になり得ます。
表は横にスクロールできます
| 問い | 確認する箇所 |
|---|---|
| 外部PRのheadを取得しているか | checkoutのref・repository、独自fetch処理 |
| 取得したコードを実行するか | build/test/install、設定・依存読込み |
| 外部入力がコマンドへ入るか | PR本文、branch名、生成ファイルの扱い |
| artifact経由で外部内容を受け取るか | 生成元runと内容の信頼性、展開後の用途 |
取得後に実行する経路が残るなら、管理処理とPRコードの検証を分離する設計へ戻ります。別workflowに分けても、権限のある側で未信頼artifactを実行すれば境界は保てません。GitHubの安全性資料も、workflow_run等で受け取ったartifactを慎重に扱うよう案内しています。GitHub:Secure use reference(新しいタブで開く)
イベントポリシーによる停止も分けて確認する
workflowが起動しない場合は、secret未提供とは別に、組織・repositoryのActions event policyが適用されていないかを確認します。ポリシーで止まっているrunへsecretを追加しても原因は解消しません。insightsや設定の閲覧権限がない場合は、対象workflowとイベントを添えて管理者へ確認します。
2026年10月20日時点のGitHubのpull_request_target資料は、対象public repositoryに対する既定ポリシーと、evaluateからenforcementへ移る予定を案内しています。適用条件や日程は変更され得るため、変更前に同資料と自分の環境のpolicyを確認してください。この記事を理由にポリシーを解除したり、unsafeなcheckoutを許可したりする必要はありません。
確認の終点を「認証成功」だけにしない
変更後は、secretなしのfork PR、本体branch、必要なら信頼済みの認証処理という経路を別々に確認します。認証先へ接続するテストは、許可された検証環境で行い、secretやtokenをログへ出さないでください。
表は横にスクロールできます
| 経路 | 期待する結果 | 実際に記録すること |
|---|---|---|
| fork PRの検証 | 許可したsecretなし検査が動く | 実行済み/省略した検査 |
| base側の管理処理 | 必要な管理操作だけを行う | PRコードを実行しないことの確認 |
| 信頼済み認証処理 | 指定commitと必要範囲だけを扱う | 対象・権限・結果・残る未確認 |
完了とは、すべてのPRへsecretを渡せたことではありません。どの入力を信頼し、どの検査をいつ実行するかが説明でき、外部変更を権限のある実行経路へ無条件に持ち込まないことです。本文は公式仕様に基づく設計・診断手順で、特定repositoryのworkflow実行や安全性監査を完了した報告ではありません。
