【ITニュース解説】CI Secrets Are Empty in Fork Pull Requests: The Safe Patterns That Actually Work
2026年10月12日に「Dev.to」が公開したITニュース「CI Secrets Are Empty in Fork Pull Requests: The Safe Patterns That Actually Work」について初心者にもわかりやすく解説しています。
ITニュース概要
GitHub Actionsでは、フォークされたプルリクエスト(PR)でセキュリティのためシークレット(認証情報)は提供されない。これはPRのコードが信頼できないためだ。対応策は、シークレットなしで動くように修正するか、PRのコードをビルド後に別の安全なワークフローでシークレットを使う処理を行う二段階方式が有効だ。
ITニュース解説
GitHub Actionsは、ソフトウェア開発の自動化において非常に強力なツールである。コードの変更が適切にテストされ、新しいバージョンが自動的にデプロイされるなど、開発プロセス全体を効率化する上で欠かせない。しかし、この便利なツールを使いこなす上で、システムエンジニアを目指す初心者が特に理解しておくべき重要な点が一つある。それは、「Secrets(シークレット)」という機密情報が、フォークされたリポジトリからのプルリクエスト(PR)でどのように扱われるか、という問題だ。
もし、あなたが書いたCI(継続的インテグレーション)のジョブが、自分のリポジトリのブランチでは正常に動作するのに、他の開発者から送られてきたフォークPRではエラーになるという状況に遭遇したら、それは設定ミスではない。GitHub Actionsは、フォークされたリポジトリからトリガーされたpull_requestイベントの実行において、リポジトリのSecretsを意図的に提供しない設計になっている。加えて、GitHubが自動的に発行するGITHUB_TOKENというトークンも、読み取り専用の権限に制限される。これはセキュリティを確保するためのGitHubの設計であり、Secretsを有効にするための設定オプションは存在しない。
この問題に直面した際、エラーメッセージが直接的に「Secretsが空です」と示すことは稀だ。多くの場合、「入力が必須なのに提供されていません」「認証情報がロードできませんでした」「HTTP 401 Unauthorized」といった形で、Secretsが空であることに起因する間接的なエラーとして現れる。同じコミット、同じワークフローであるにもかかわらず、自分のリポジトリでは成功し、フォークPRでは失敗するというのが、この現象を見分ける特徴だ。Secretsが実際に利用可能かどうかを確認するには、ワークフロー内でecho "has NPM_TOKEN: ${{ secrets.NPM_TOKEN != '' }}"のようなスクリプトを実行するとよい。フォークPRでは「has NPM_TOKEN: false」と表示され、「fork: true」という出力と共に、Secretsが利用できないことが明確に確認できるだろう。
では、なぜGitHubはフォークPRでSecretsを提供しないのだろうか。これはセキュリティ上の非常に重要な理由があるからだ。PRに含まれるコードは、そのPRを作成した外部の開発者が自由に制御できる。GitHubアカウントを持つ誰でも、公開リポジトリに対してPRを開くことが可能であり、もし悪意のある開発者がPRのコードを通じてリポジトリのSecretsにアクセスできてしまうと、デプロイキーやAPIトークンなどの機密情報が容易に盗み出されてしまうリスクがある。たとえPRがテストファイルや設定ファイルの変更に見えても、その中に巧妙に仕組まれたスクリプトによってSecretsが外部に漏洩する可能性をGitHubは懸念しているのだ。そのため、GitHubは「信頼できないコードが実行される」という境界において、Secretsを提供せず、GITHUB_TOKENも読み取り専用にすることで、情報漏洩のリスクを最小限に抑える設計を採用している。このことから、信頼の境界は「誰のコードが実行されているか」という点にあり、「どのリポジトリのブランチか」ではないということを理解しておく必要がある。
この制約の中で、Secretsが必要な処理を安全に実行するにはいくつかの効果的なパターンがある。 最も推奨されるアプローチは、まずCIステップがSecretsを必要としないように設計を改めることだ。多くの「Secretsが必要」とされるCIステップは、実際にはスタブ(模擬的なサービス)やサービスコンテナで代替できる場合が多い。例えば、ステージングAPIを直接呼び出すテストではなく、ローカルで動作する模擬APIを利用するようにテストを書き換えたり、パッケージレジストリへのログインが必要なのは公開時だけで、それ以外のビルドやテストでは不要にしたりする工夫が考えられる。サービスコンテナや一時的なローカル環境で完結する依存関係であれば、SecretsなしでフォークPRでも正常に動作する。Secrets依存を排除できれば、それが最も安全でシンプルな解決策となる。どうしてもSecretsが必要な場合は、そのステップをフォークPRではスキップし、その旨を明確なメッセージで表示することが重要だ。これにより、コントリビューターがPRのテスト結果を見て混乱するのを防ぐことができる。
次に、Secretsがどうしても必要なステップを安全に実行するためのパターンとして、「workflow_runパターン」がある。これは2段階のワークフローを組み合わせる方法だ。最初のワークフロー(例えばpr-build.yml)はpull_requestイベントでトリガーされ、SecretsなしでPRのコードをビルドし、必要な成果物(アーティファクト)を生成してアップロードする。このワークフローでは、信頼できないPRのコードが実行されるため、Secretsは一切使用しない。次に、2番目のワークフロー(例えばpr-deploy-preview.yml)は、最初のワークフローの完了(通常は成功時のみ)をworkflow_runイベントで検知してトリガーされる。この2番目のワークフローは、あなた自身のリポジトリのコンテキストで実行されるため、Secretsにアクセス可能だ。ここでは、1番目のワークフローで生成されたアーティファクトをダウンロードし、Secretsを使ってデプロイや追加のテストなどの処理を行う。この際、最も重要な注意点は、ダウンロードしたアーティファクトを「信頼できないデータ」として扱うことだ。アーティファクトに含まれるスクリプトなどを直接実行してはならない。あくまでデータとして扱い、Secretsにアクセスする処理自体は、あなた自身の信頼できるリポジトリ内のスクリプトやコードで行うべきである。また、workflow_runで実行されたジョブは、PRのチェックリストに自動的に表示されないため、GitHubのStatuses APIを使って明示的にPRにステータスを投稿し、レビューアが結果を確認できるようにする必要がある。
別の方法として、「pull_request_target」トリガーを使うパターンもある。このトリガーは、Secretsにアクセスできる状態で実行される。しかし、これは非常に慎重に扱うべきだ。デフォルトでは、pull_request_targetワークフローはベースブランチ(通常はmainやmaster)のコードをチェックアウトする。この状態であれば比較的安全だが、もしgithub.event.pull_request.head.shaといったPRのヘッドコミットのコードをチェックアウトし、そのコードを実行してしまうと、悪意あるPRによってSecretsが漏洩する「pwn request」と呼ばれる深刻な脆弱性が生まれてしまう。そのため、pull_request_targetを利用する際は、決してPRのコードを実行しないか、あるいはGitHubの「Deployment environments with required reviewers(レビュー必須のデプロイ環境)」と組み合わせて、メンテナンス担当者の承認がなければSecretsが利用できないようにするべきだ。これにより、人間がPRの内容をレビューし、安全だと判断してからSecretsを渡すことができる。
最後に、Dependabotが作成するPRも、通常のフォークPRと同様にリポジトリのSecretsが直接利用できない点に注意が必要だ。DependabotのPRは、独自のDependabot専用のSecretsストアに保存されたSecretsを使用する。そのため、ActionsのSecretsに加えて、DependabotのSecretsセクションにも同じ認証情報を登録する必要がある。これにより、Secretsの管理が二重になり、メンテナンスの手間が増えるが、これはDependabotのセキュリティ設計によるものだ。
まとめとして、GitHub ActionsでフォークPRを扱う際のSecretsの挙動は、セキュリティ上の理由から非常に厳格に設計されていることを理解するのが出発点だ。まず、CIのステップを見直し、可能な限りSecretsを使わないように改修することが最善策である。それが難しい場合は、workflow_runパターンを用いて、PRのコードをSecretsなしでビルドし、その成果物を信頼できるワークフローでSecretsと共に処理するという安全な2段階のワークフローを構築する。pull_request_targetを使う際は、PRのコードを実行しない、またはレビューアによる承認を必須にするなど、極めて慎重な運用が求められる。これらの知識を身につけ、安全で効率的なCI/CDパイプラインを構築してほしい。