2026年に報告されたCVEは、1日あたり前年比131%増加しています。

CI/CDセキュリティ

エグレスポリシーでGitHub Actionsからの情報流出を防ぐ

CIジョブはシークレットを保持し、ついさっきダウンロードしたコード、つまりアクションやパッケージとそのインストールスクリプトを実行します。そのコードのどれかが悪意あるものなら、シークレットを盗む最も簡単な方法はサーバーに送信することです。エグレスポリシーは、ジョブがどのサーバーに到達できるかを決め、それ以外をブロックします。

更新日

CIジョブからシークレットが流出する経路

ジョブは、リポジトリのトークン、渡されたシークレット、引き受けたクラウドの認証情報にアクセスできます。ジョブ内で実行されるコードはそれらを読み取れます。そして、次のような方法で外部に持ち出せます。

  • ネットワーク経由。攻撃者が管理するサーバーへのリクエストです。エグレスポリシーが塞ぐのはこの経路です。
  • ログ経由。シークレットを、多くの場合エンコードしてジョブのログに出力します。2025年3月、CISAは侵害されたtj-actions/changed-filesアクションがこの方法でシークレットを漏えいさせたと報告しました。
  • 出力経由。アーティファクト、キャッシュ、またはジョブのトークンでプッシュされたコミットです。

悪意あるパッケージでなくても同じことが起こります。ワークフロー内のAIエージェントは、Issueやプルリクエストに隠されたプロンプトインジェクションによって乗っ取られ、同じ経路を使うことがあります。

エグレスポリシーの役割

多くのジョブが到達する必要があるのは、パッケージレジストリ、コンテナレジストリ、ソースのホスト、いくつかのサービスといった、限られた接続先だけです。エグレスポリシーはその一覧を許可し、それ以外をすべてブロックします。デフォルト拒否のポリシーでは、未知のホストへのリクエストは失敗し、シークレットはジョブの中にとどまります。

What happens when malware in a build tries to send your secrets out Left, a runner that allows all outbound traffic: the build reaches its package registry and publishes its output, then a malicious install hook sends the build's secrets to an attacker's server, and they arrive. Right, CRACI with a default-deny egress policy: the registry and publish connections are allowed, the connection to the attacker's server is blocked at the policy, and an alert is sent. The policy allows only what the build needs, so it works even against an attack nobody has seen before. Any outbound allowed build job holds your tokens and keys malicious install hook runs no egress policy package registry publish output attacker server allowed allowed secrets sent to the attacker CRACI default-deny egress policy build job on CRACI holds your tokens and keys malicious install hook runs egress policy: only what the build needs package registry publish output attacker server allowed allowed blocked blocked, and you get an alert
The policy allows only what the build needs, instead of looking for known-bad hosts, so it stops a new attack the first time it runs.

ただし、すべての経路を塞ぐわけではありません。

  • シークレットがログに出力されることは防げません。ログを非公開にし、アクションをコミットSHAで固定してください。
  • 許可した接続先でもデータを持ち出せるため、許可リストは最小限にしてください。
  • どのパッケージが悪意あるものだったかはわかりません。それはパッケージのスクリーニングとSBOMの役割です。

適用する3つの方法

  • ランナー上のエージェント。StepSecurity Harden-Runnerは、ジョブの最初のステップとして追加されます。各接続をそれを行ったステップに対応付け、監査モードでベースラインを作成し、許可リスト外へのエグレス通信をブロックします。
  • ポリシーを組み込んだランナー。CRACIは、ランナー自体としてポリシーを適用します。ほかのランナープロバイダーもネットワーク制御を提供しており、DepotのLinuxランナーのエグレスフィルタリングや、Namespaceのブロック型または勧告型のエグレスポリシーなどがあります。
  • 自社のネットワーク。自社で構成・保守するファイアウォールやプロキシの背後に置いたセルフホストランナーです。

ビルドを壊さずに導入する

  1. 観察する。数回の実行で、ジョブが行うすべての接続を記録します。
  2. 許可する。ジョブが実際に必要とするものから許可リストを作成します。
  3. ブロックする。デフォルト拒否に切り替え、違反を監視します。
  4. 見直す。新しい違反はすべて、許可漏れのソースかインシデントのどちらかとして扱います。

CRACIでの実現方法

CRACIでは、エグレスポリシーはランナーの一部です。ジョブ開始前に検証され、不明なフィールドは拒否され、フェイルクローズで動作します。組み込みのプリセットが一般的なパッケージソースをカバーし、カスタムのソースと接続で残りを追加します。ジョブのトレースにはすべての接続が記載され、ブロックされた接続はそれぞれ理由付きの違反として示されます。プロキシがパッケージを認識するため、同じ記録がジョブのSBOMになります。APIはSBOM、ネットワークトレース、来歴を返します。

CRACIにはまだ専用の監査モードがなく、ロードマップに掲載されています。ネットワークポリシーがない場合、ジョブの通信は許可され、トレースに記録されるため、適用する前にポリシーに何が必要かを確認できます。CRACIはLinux上でGitHub Actionsのジョブを実行します。CI/CDセキュリティツールの比較とCRACIとStepSecurityの比較をご覧ください。

CIのエグレスポリシー:よくあるご質問

CIにおけるエグレスポリシーとは何ですか?

CIジョブが行える外向きのネットワーク接続についてのルールセットです。ジョブは必要なパッケージレジストリやサービスには到達でき、それ以外の接続先はすべてブロックされます。

エグレスポリシーがあれば、tj-actionsの侵害は防げましたか?

それだけでは防げませんでした。この事例では、CISAの報告によると、シークレットは外部サーバーに送信されたのではなく、ワークフローのログを通じて漏えいしました。エグレスポリシーはネットワーク経路を塞ぎます。ログ経路には、アクションをコミットSHAで固定し、ログを非公開にすることで対処します。

エグレス通信をブロックするとビルドが壊れませんか?

ビルドに必要なソースがポリシーから漏れていれば、壊れることがあります。まずジョブの接続先を記録し、それを基に許可リストを作成してから、ブロックしてください。CRACIでは、組み込みのプリセットが一般的なパッケージソースをカバーし、ブロックされた接続は理由とともにジョブのトレースに表示されます。

GitHubホステッドランナーでエグレスポリシーを使えますか?

はい。StepSecurity Harden-Runnerのようなエージェントをジョブに追加すれば使えます。または、CRACIのように、ランナー自体がポリシーを適用するランナーにジョブを移行する方法もあります。

1つのジョブにエグレスポリシーを適用

ワークフローを1つCRACIで実行し、行われたすべての接続、許可リストに必要なホスト、取得したもののSBOMを確認してください。

デモを予約