Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Your GitHub Actions Workflow Has More Power Than Most Developers Realize

2026年10月06日に「Dev.to」が公開したITニュース「Your GitHub Actions Workflow Has More Power Than Most Developers Realize」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

GitHub Actionsワークフローは単なる自動化を超え、強力な権限を持つためセキュリティの境界線だ。設定次第でリポジトリ改変やシークレット漏洩のリスクがある。ワークフローには最小限の権限を与え、危険なトリガーやサードパーティ製アクションに注意しよう。ワークフローを「コードを実行するサービス」と捉え、その権限を常に意識し安全に運用することが重要だ。

ITニュース解説

GitHub Actionsは、コードの自動テスト、ビルド、デプロイといった開発作業を効率化するための強力なツールである。しかし、多くの開発者がその真の機能や、それに伴うセキュリティリスクについて十分に理解していない場合がある。単なる「自動化スクリプト」として捉えられがちだが、実際にはコードリポジトリや、場合によっては本番環境にまで影響を及ぼす可能性のある、システムのセキュリティ境界の一部として機能している。

GitHub Actionsのジョブは、リポジトリの内容を読み取ったり、コードを変更したり、新しいリリースを作成したり、ソフトウェアパッケージを公開したり、機密情報(シークレット)にアクセスしたり、クラウドプロバイダーと通信して本番環境にデプロイしたり、プルリクエストにコメントしたり、リポジトリの状態を変更したりといった、非常に幅広い操作を実行できる。これは、あなたのCI(継続的インテグレーション)パイプラインが単なる自動化に留まらず、システムのセキュリティの一部として慎重に扱うべきものであることを意味する。そして、多くのワークフローは、それらを管理している開発者が気づかないうちに、必要以上の権限を持っている可能性がある。

すべてのGitHub Actionsジョブは、GITHUB_TOKENという特別な認証情報を受け取る。これはGitHubによって自動的に生成され、このトークンに与えられた権限によって、ワークフローがリポジトリ内で何ができるかが決まる。このため、ワークフロー設定ファイル(YAMLファイル)内のpermissionsセクションは非常に重要になる。例えば、以下のようにpermissionsを設定すると、ワークフローはリポジトリの内容を読み取る権限のみを持つことになる。

1permissions:
2  contents: read

明示的に権限を考えずにいると、開発者は意図せずワークフローに必要以上の権限を与えてしまうことがよくある。より安全な考え方は、「各ワークフローには、そのジョブを完了するために最低限必要な権限のみを与える」というシンプルな原則だ。例えば、コードをチェックアウトしてテストを実行するだけのジョブであれば、リポジトリの内容を書き換える権限は必要ないだろう。テストジョブは、リリースの作成、issueの変更、パッケージの公開、リポジトリ内容の書き込みなどの権限を持つべきではない。権限は、GitHub Actions全体への一般的な信頼ではなく、個々のジョブに属するものとして考えるべきである。

特に注意が必要なワークフローのトリガーの一つに、pull_request_targetがある。これはpull_requestと似ているように見えるが、そのセキュリティモデルは大きく異なる。通常のpull_requestトリガーは、フォークされたリポジトリからのプルリクエストに対して強い制限を設け、リポジトリのシークレットを非公開にし、ワークフローに読み取り専用のトークンを与える。しかし、pull_request_targetは、ベースリポジリの信頼されたコンテキストで実行され、リポジトリのシークレットや読み書き可能なGITHUB_TOKENを受け取ることができる。これは、プルリクエストへのラベル付けやトリアージ、認証が必要なチェックなど、特定の用途には非常に便利だが、信頼できないコードと組み合わせてしまうと非常に危険になる。

危険なパターンとして「Pwn Request」が挙げられる。これは、pull_request_targetトリガーでワークフローを実行し、プルリクエストの作成者のコード(github.event.pull_request.head.shaで指定されるコード)をチェックアウトして実行する場合である。一見すると、投稿されたコードをテストしたいだけのように見えるが、これによって特権的なワークフロー内で、信頼できないプルリクエストのコードが実行されることになる。そのコードは、package.json、インストールスクリプト、テストスクリプト、ビルドスクリプト、設定ファイルなどを変更する可能性があり、悪意のあるコードを実行できてしまう。GitHubも、特権的なpull_request_targetワークフローでフォークされたコードを実行することに対して明示的に警告している。問題はコードのチェックアウト自体ではなく、チェックアウトした信頼できないコードを実行することから始まるのだ。

npm installのようなコマンドが単なるファイルのダウンロードではないことも、開発者が忘れがちな点だ。npm installを実行すると、依存関係にインストールスクリプトが含まれていたり、自身のレポジトリにライフサイクルスクリプトが定義されていたりする場合がある。ビルドツールも設定に基づいてコードを実行することがあるため、信頼できないコードが依存関係やビルド設定を変更できる状況で、特権的なジョブ内でnpm installを実行することは、実質的にプルリクエストによって制御されたコードを実行することと同じ意味を持つ可能性がある。この考え方はmake、pip install、./gradlew build、./gradlew build、docker buildなど、他のCIコマンドにも当てはまる。CIコマンドはコード実行の境界であると認識し、慎重に扱うべきだ。

ワークフローにenv: API_KEY: ${{ secrets.API_KEY }}のようにシークレットが含まれている場合、そのジョブ内で実行されるどんなコードでも、そのシークレットとやり取りする可能性がある。GitHubは、ジョブやアクションがワークフローに利用可能なシークレットにアクセスできるため、最小限の権限を持つ認証情報を使用することを推奨している。「このステップが侵害された場合、何が盗まれたり変更されたりする可能性があるか?」という問いは、ジョブの構成を考える上で非常に重要である。

パイプラインがプルリクエストをテストし、その後何かを公開する必要がある場合でも、すべてを一つの巨大な特権ジョブにまとめてはいけない。信頼の境界を意識して考えるべきだ。例えば、まずプルリクエストのコードをビルド・テストするジョブは、シークレットを持たず、読み取り専用のトークンで実行する。そして、生成された成果物(アーティファクト)を次のジョブに渡し、その次のジョブで、信頼されたワークフローとして公開やデプロイといった特権操作を行う。このように分離することで、システムの安全性をはるかに容易に担保できる。

サードパーティのアクションも、アプリケーションの依存関係と同様に注意深くレビューする必要がある。多くの開発者はnpmパッケージは慎重にレビューするが、uses: some-user/some-action@v2のような記述は深く考えずに使ってしまいがちだ。しかし、サードパーティのアクションはあなたのワークフロー内で実行されるため、もしそのアクションが侵害されていた場合、リポジトリのシークレットにアクセスしたり、ワークフローのGITHUB_TOKENを悪用したりする可能性がある。GitHubは、変更不可能な参照が必要な場合は、アクションを完全なコミットSHAでピン留めすることを推奨している。uses: vendor/action@v2のようにタグに依存するのではなく、uses: vendor/action@3c2f...full-commit-shaのように正確なコミットSHAを指定することで、より制御されたセットアップが可能になる。タグは便利だが、変更される可能性があるため、完全なコミットSHAを使用すれば不変性が保証される。

多くの場合、開発者はアプリケーションの依存関係ツリー(例:react、express)を意識するが、CIパイプラインにも同様の依存関係ツリー(例:actions/checkout、setup-node、デプロイアクション、セキュリティスキャナー、カスタムサードパーティアクション)があることを認識すべきである。これらのCIパイプラインの依存関係も、アプリケーションコードよりも高い権限で実行される可能性があるため、慎重なレビューが必要だ。

長期間有効なクラウド認証情報(例:AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY)をGitHubに保存する一般的なデプロイ設定は、リスクが高い。より良いモデルは、短期間の認証情報を使用することだ。GitHub ActionsはOpenID Connect (OIDC) をサポートしており、ワークフローが短期間のIDトークンを要求し、それをクラウドプロバイダーと交換することで一時的な認証情報を取得できる。これにより、リポジトリ設定に永続的なクラウドシークレットを保存する必要がなくなるため、セキュリティが大幅に向上する。

セルフホストランナーを使用する場合、脅威モデルが大きく変わる。GitHubがホストするランナーは通常一時的で隔離されているが、セルフホストランナーはそうではない場合が多い。もしあなたのランナーが内部ネットワーク、Dockerソケット、本番データベース、クラウドメタデータ、SSHキー、マウントされたファイルなどにもアクセスできる場合、そこで信頼できないコードを実行することははるかに危険になる。GitHubは、侵害されたランナーがシークレットやランナー環境に利用可能な他のリソースを公開する可能性があると具体的に警告している。「このマシンはGitHub自身ではアクセスできない何に到達できるのか?」という問いは、ネットワークアクセスだけでなく、保存された認証情報も含めて非常に重要である。

開発者は「ビルド成功、テスト成功、デプロイ成功」という結果を見て、すべてが問題ないと安易に判断しがちだ。しかし、ワークフローのセキュリティは、コマンドが成功したかどうかだけではなく、「それらのコマンドが実行されている間にどのような権限を持っていたか」にかかっている。完璧に成功したワークフローでも、セキュリティ設計が不十分である可能性は十分にある。

今すぐにGitHub Actionsのワークフローで以下の8つの項目を監査すべきだ。

  1. トークン権限: ワークフロー内のpermissions:設定を確認し、もしそれがなければ明示的に定義すべきか問いかける。常に最低限必要な権限を優先する。
  2. pull_request_target: このトリガーを使用しているワークフローがあれば、その存在理由を正確に理解する。プルリクエストのコードをチェックアウトして実行している場合は特に慎重になる。
  3. シークレット: secrets.を使用している箇所すべてについて、「このジョブは本当にそれが必要か?」と問う。後のステップで必要かもしれないからといって、無闇にシークレットを利用可能にしない。
  4. サードパーティActions: すべてのuses:の行をレビューし、誰が保守しているのか、まだ必要か、コミットSHAでピン留めされているか、ジョブがどのような権限を持っているかを確認する。
  5. 公開操作: npm publish、docker push、gh release、terraform apply、kubectl、aws、gcloud、azなど、外部システムを変更する可能性のあるすべてのコマンドを特に注意深く監査する。
  6. 信頼できない入力: issue、プルリクエスト、ブランチ名、コミットメッセージ、その他の外部ソースからの値をシェルコマンドに挿入する際には注意が必要だ。ワークフローファイルもコードであり、信頼できない文字列は他の場所での信頼できない入力と同様に扱うべきである。
  7. セルフホストランナー: ランナーが何にアクセスできるかを問いかける。内部ネットワークアクセスを持つランナーは、隔離された一時的なランナーとは全く異なる脅威範囲を持つ。
  8. ビルドとデプロイの分離: 可能であれば、ビルドとデプロイのステップを分離する。デプロイが後に発生するからといって、ビルドジョブが自動的に本番環境への権限を継承すべきではない。

より安全な考え方は、「GitHub Actionsは私のCIを実行する」と考えるのではなく、「GitHub ActionsはID、権限、認証情報、ネットワークアクセス、外部機能を持つコードを実行する」と考えることだ。この視点の変化は、ワークフローのレビュー方法を根本的に変える。ワークフローは、単なるYAMLファイルというよりは、小さな本番サービスに近いものとして捉えられるようになる。

多くの開発者は、アプリケーションのすべてのエンドポイントに管理者権限を与えることは決してしないだろう。しかし、「これは単なるビルドワークフローだから」という理由で、CIパイプラインには広範な権限を与えてしまうことがある。実際はそうではない。あなたのワークフローは、リポジリを変更したり、シークレットにアクセスしたり、パッケージを公開したり、インフラをデプロイしたり、本番システムに認証したりする能力を持っている可能性があるのだ。

だから次に.github/workflows/を開くときは、「このパイプラインは動作するか?」という問いだけでなく、「もしこのパイプラインのいずれかのステップが信頼できなくなった場合、何ができるのか?」と問いかけてほしい。この問いかけこそが、はるかに重要かもしれない。

関連コンテンツ

関連IT用語