あなたのワークフロー、`@v4`で指定してませんか?
GitHub Actionsでこんな書き方、していませんか?
- uses: actions/checkout@v4
- uses: actions/setup-node@v4公式ドキュメントでもこの書き方が載っているし、動いているから問題ないと思いますよね。でも実は、この@v4という指定はセキュリティ的に危険です。2025年3月に実際に起きたtj-actions/changed-files事件では、この仕組みが悪用され、23,000以上のリポジトリのCI/CDシークレットが漏洩するリスクにさらされました。
本記事では、タグ指定が危険な理由と、コミットハッシュで固定する具体的な方法を解説します。
`actions/checkout@v4`の裏側で何が起きているか
まず、@v4が何を意味しているかを理解しましょう。
GitHub Actionsのusesで指定する@以降は、Gitのref(参照)です。ブランチ名、タグ名、コミットハッシュのいずれかを指定できます。
# タグ指定(よく見る書き方)
- uses: actions/checkout@v4
# ブランチ指定(非推奨)
- uses: actions/checkout@main
# コミットハッシュ指定(最も安全)
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683ここで重要なのは、Gitのタグは「書き換え可能」だということ。タグは特定のコミットに貼るラベルに過ぎず、リポジトリの管理者(あるいは管理者権限を奪った攻撃者)はいつでも同じタグ名を別のコミットに貼り直せます。
【タグ指定の落とし穴】
昨日: v4 → コミットA(正常なコード)
今日: v4 → コミットB(攻撃者が差し替えたコード)← 同じ「v4」なのに中身が違う!
あなたのワークフローは「v4」を信頼して実行
→ 攻撃者のコードが本番CIで動く一方、コミットハッシュは改ざんできません。SHA-1ハッシュはコミットの内容から一意に決まるため、同じハッシュで中身を変えることは事実上不可能です。
実際に起きた:tj-actions/changed-files事件
2025年3月14日、GitHub Actionsで広く使われていたtj-actions/changed-files(プルリクエストの変更ファイルを検出するアクション)が侵害されました(CVE-2025-30066)。
何が起きたかを時系列で整理します。
- 攻撃者がリポジトリの書き込み権限を持つGitHubトークンを取得
- 正規のメンテナンスbot(renovate[bot])を装って、悪意のあるコミットをpush
- そのコミットに既存のバージョンタグ(v4等)を貼り替え
@v4で指定していた全リポジトリのワークフローで、悪意のあるコードが実行される- 攻撃コードはCIランナーのメモリ上のシークレット(APIキー、トークン、RSAキー等)をビルドログに出力
23,000以上のリポジトリがこのアクションを利用しており、パブリックリポジトリのビルドログは誰でも閲覧できるため、シークレットが大規模に露出するリスクがありました。
この事件の教訓は明確です。タグは信頼の根拠にならない。コミットハッシュで固定していれば、タグが書き換えられても影響を受けなかった。
コミットハッシュで固定する方法
Step 1:使用中のアクションのコミットハッシュを調べる
アクションのGitHubリポジトリで、使いたいバージョンタグに対応するコミットハッシュを確認します。
# actions/checkoutのv4タグが指すコミットハッシュを確認
git ls-remote --tags https://github.com/actions/checkout.git | grep 'v4$'
# → 11bd71901bbe5b1630ceea73d27597364c9af683 refs/tags/v4または、GitHubのリポジトリページでタグを選択し、コミットハッシュ(フルSHA)をコピーする方法でもOKです。
Step 2:ワークフローを書き換える
# ❌ Before: タグ指定(書き換え可能)
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/cache@v4
# ✅ After: コミットハッシュ固定(改ざん不可)+ コメントでバージョン明記
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.0ポイントは、ハッシュの末尾にコメントでバージョンを書いておくこと。ハッシュだけだと何のバージョンか分からなくなるので、# v4.2.2のように添えるのがベストプラクティスです。
Step 3:既存ワークフローを一括変換する
手動でハッシュを調べるのが面倒な場合は、pin-github-actionというCLIツールで一括変換できます。
# pin-github-actionのインストール
npm install -g pin-github-action
# ワークフローファイルを一括変換
pin-github-action .github/workflows/ci.yml実行すると、タグ指定をコミットハッシュに自動変換し、コメントにバージョンを残してくれます。
Dependabotで自動更新する仕組み
「ハッシュで固定したら、新しいバージョンが出た時に手動で更新するの?」という疑問が出ますよね。ここはDependabotに任せましょう。
リポジトリのルートに以下のファイルを追加するだけで、GitHub Actionsのアクション更新をDependabotが自動でPRしてくれます。
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"Dependabotは新しいバージョンが出ると、コミットハッシュとコメントのバージョン番号を両方更新したPRを自動で作成してくれます。レビューしてマージするだけなので、ハッシュ固定でも運用負荷はほとんど変わりません。
GitHub Actionsのセキュリティを強化する関連記事
コミットハッシュの固定はサプライチェーン攻撃対策の第一歩です。GitHub運用のセキュリティ全般もあわせて強化しましょう。
GitHub・セキュリティ
- 「それ、上げちゃダメ!」GitHub管理で絶対守るべきセキュリティルールと対処法 – .gitignore、2FA、アクセス権限管理などGitHubセキュリティの基本を網羅
- システム開発を成功させるために知っておきたい「GitHub」の基本 – リポジトリの公開設定やアクセス管理の基礎知識
- リリース前に必ず確認!バイブコーディング&非エンジニア向けWebアプリ安全チェックリスト – CI/CDを含むリリース前のセキュリティチェック全般
CI/CD・インフラ
- AWS CLIで開発が爆速になる!セットアップからCloudWatch・Lambda活用まで実用コマンド付き – GitHub ActionsからAWSにデプロイする際のCLI設定とシークレット管理
- IaC(Infrastructure as Code)とは?インフラをコードで管理する3つのメリット – CI/CDパイプライン自体をコードで管理・監査する考え方
まとめ:タグは「ラベル」、ハッシュは「指紋」
本記事のポイントを整理します。
@v4のタグ指定は書き換え可能。攻撃者がタグを悪意あるコミットに貼り替えると、あなたのCIで攻撃コードが動く- tj-actions事件(CVE-2025-30066)で実際にこの手法が悪用され、23,000以上のリポジトリが影響を受けた
- コミットハッシュで固定すれば、タグが書き換えられても影響を受けない
- コメントにバージョンを明記(
# v4.2.2)して可読性を確保 - Dependabotで自動更新すれば、ハッシュ固定でも運用負荷はほぼゼロ
タグは「ラベル」です。貼り替えられます。コミットハッシュは「指紋」です。偽造できません。この違いを理解するだけで、CI/CDの安全性は一段上がります。今日のうちに自分のワークフローを開いて、@v4を見つけたらハッシュに置き換えてみてください。5分でできる、最もコスパの高いセキュリティ対策です。
