テック技報最新号へ →
セキュリティ

pull_request_target とキャッシュポイズニングの危険を潰す

フォークからの PR を pull_request_target で扱うワークフローは「書き込み権限+シークレット付きで外部コードを動かす」危険があるため、使い方を限定し、静的解析で検出する。

@t6adev · 2026-10-09
#github-actions#supply-chain#ci#oidc

何を解決するか / 背景

  • TanStack の npm 侵害は、pull_request_target の強い権限、GitHub Actions のキャッシュポイズニング、ランナーのメモリからの抽出を連鎖させ、最終的に OIDC トークン(npm publish 権限)を得たとポストモーテムで説明されている(@t_wada の紹介)。
  • 過去 18 か月の主要な OSS サプライチェーン攻撃は、ほぼ .github/workflows の YAML に行き着く。GitHub Actions は「リリース鍵置き場」に近い(@labelmake)。

対策チェックリスト

  1. pull_request_target では PR の head を checkout してビルド・実行しない。ラベル付けやコメントなど、コードを実行しない処理に限定する。
  2. 外部コードを扱うなら pull_request(読み取り権限・シークレットなし)で動かし、結果だけを workflow_run で受け取る。
  3. ワークフロー先頭で permissions: {} → ジョブごとに最小権限を付与。id-token: write は publish ジョブだけ。
  4. リリースジョブは信頼できないジョブとキャッシュを共有しない(キャッシュキーを分ける/リリース時はキャッシュを使わない)。
  5. publish は Environment(承認者付き)に閉じ込める。
  6. 静的解析で検出: ghasec(セキュリティ重視の GitHub Actions 静的解析、@matsuu の紹介)や zizmor / actionlint を CI に入れる。
yaml
on: pull_request_target
permissions: {}
jobs:
  label:
    permissions: { pull-requests: write }
    runs-on: ubuntu-latest
    steps:
      - run: echo "コードは checkout しない"

注意点

  • ${{ github.event.pull_request.title }} などを run: に直接埋め込むとスクリプトインジェクションになる。環境変数経由で渡す。
  • AI エージェント(Gemini CLI の GitHub Action など)をワークフローで動かす場合、ヘッドレス環境でワークスペースが自動信頼される不備が報告された。外部入力を読むエージェントには明示的な信頼設定と最小権限を。

出典

X の元の投稿を開く