⭐️Pwn Request(GitHub Actions)

信頼できない Pull Request のコードを、書き込み権限やシークレットを持った特権コンテキストで実行してしまう脆弱性パターン。GitHub Security Lab が名付けた。

まず前提:GitHub Actions は「PR が来たら自動でテストを回す」ような自動化ができる。このとき Actions には、リポジトリを操作するための鍵(GITHUB_TOKEN)や API キー等の Secrets が渡されることがある。

何が問題か(たとえ話): あなたのリポジトリは「自分の家」だと思ってほしい。誰でも改善提案(PR)を送れるように玄関を開けている。ここで危険なのが pull_request_target というトリガー:

  • 通常の pull_request は「提案者の権限(=ほぼ何も持っていないゲスト)」で動くので安全。
  • ところが pull_request_target は、他人(fork)から来た PR でも「家主であるあなたの権限(金庫の鍵つき)」でワークフローが走る。
  • そのワークフローが、送られてきた PR のコードを取り込んで(actions/checkout)テストやビルドで実行すると――赤の他人が書いたコードを、あなたの鍵を握ったまま家の中で走らせることになる。

攻撃者は PR のコードにこっそり Secrets を外部に送信する 処理などを仕込む。結果、API キーの窃取・リポジトリの改ざん・パッケージの不正公開などが起きる。

攻撃の流れ(ステップ):

  1. 攻撃者があなたのリポジトリを fork する。
  2. fork 側で、テストやビルドのスクリプトに Secrets を盗む処理を仕込んだ PR を送る。
  3. あなたのリポジトリの pull_request_target ワークフローが発火。
  4. このワークフローは base(あなた側)の特権で動く = GITHUB_TOKEN(write)と Secrets を持っている。
  5. ワークフローが 攻撃者の PR ブランチを checkout して実行(=他人のコードが特権下で走る)。
  6. 仕込まれたコードが Secrets を読み取り、攻撃者の外部サーバへ送信。
  7. 攻撃者は盗んだ鍵で リポジトリ改ざん・パッケージ不正公開などを実行。
         攻撃者                          あなたのリポジトリ (base)
          │                                      │
   ① fork して悪意ある PR を作成 ───────────────▶ │
          │                                      │ ② pull_request_target が発火
          │                                      │    ┌──────────────────────────────┐
          │                                      │    │ ワークフロー実行              │
          │                                      │    │  権限 = base の特権           │
          │                                      │    │  🔑 GITHUB_TOKEN (write)      │
          │                                      │    │  🔑 Secrets (APIキー等)       │
          │                                      │    │                              │
          │   ③ checkout で「攻撃者のコード」を取り込み実行 ← ここが地雷            │
          │                                      │    │  悪意あるスクリプトが走る     │
          │                                      │    └───────────┬──────────────────┘
          │                                      │                │ ④ Secrets を読む
   ⑤ 盗んだ鍵で改ざん・不正公開 ◀── 外部へ送信 ──┘                │
          │                                                       ▼
          ▼                                              💥 API キー漏洩・乗っ取り

ポイントは 「実行される権限(base の金庫つき)」と「実行されるコード(他人の PR)」がミスマッチしていること。本来この 2 つは揃っているべき(他人のコードなら他人=無権限で動くべき)なのに、pull_request_target はそれをねじれさせてしまう。

  • 対策:
    • fork PR のコードを実行するなら、権限もシークレットも無い pull_request トリガーを使う(ゲスト権限で動かす)。
    • どうしても pull_request_target が必要なら、PR のコードは checkout・実行しない(ラベル付けなど無害な処理だけに限定)。
    • 実行が必要なら 2 段構成にする:まず「鍵なしジョブ」で他人のコードをビルド、その結果を「鍵ありジョブ」がただ反映するだけ、と役割を分ける。

「他人の PR を、自分の鍵を持ったまま動かすな」。pull_request_target × 他人のコード実行 が地雷。