GitHub Actionsのバージョン指定 vs コミットハッシュ指定:どちらを使うべき?セキュリティ視点で解説
GitHub Actionsでライブラリ(Actions)を利用するとき、こんな書き方の違いを見たことはありませんか?
# バージョン指定(タグ)
- uses: actions/checkout@v7
# コミットハッシュ指定
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1私はこれまで「公式のActionsはバージョン指定、サードパーティはハッシュ指定」というルールで運用してきました。
しかし最近、公式のActionsもハッシュ指定しているワークフローを見かけることが増えてきました。
「これってやりすぎでは?」と思いつつ調べてみたところ、ちゃんとした理由があることがわかりました。
今回は、このあたりのベストプラクティスを整理してみます。
そもそもバージョン指定(タグ)のリスクとは
- uses: actions/checkout@v7この書き方、シンプルで読みやすいですよね。
でも、セキュリティ的には注意が必要です。
タグは書き換えられる
Gitのタグは、リポジトリのオーナーがいつでも別のコミットに付け替えることができます。つまり、こういうことが起こりえます:
- 昨日の v7 と今日の v7 が、実は別のコードを指している
- 悪意のある第三者がリポジトリを侵害した場合、タグを悪意あるコードに付け替えられる
これはサプライチェーン攻撃と呼ばれる手法の一つで、実際に被害事例も報告されています。
コミットハッシュ指定のメリット
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1一方、コミットハッシュを指定すると、この問題を回避できます。
不変性(Immutability)が保証される
- コミットハッシュはコードの内容に紐づいた暗号学的なIDなので、改ざんできない
- 実行されるコードが常に同一であることが保証される
- セキュリティ監査のときに「何が実行されたか」を正確に追跡できる
コメントでバージョン番号を併記しておけば、可読性も維持できます。
公式のActionsはバージョン指定で問題ない?
ここが悩ましいポイントです。
結論から言うと、厳密にはリスクはあります。
GitHub公式の actions/* であっても、理論上はタグ書き換えのリスクは存在します。
ただし、実務上のリスクレベルはActionsの種類によって異なります。
| 対象 | リスク | 理由 |
|---|---|---|
| 公式(actions/*) | 低め | GitHubが管理。侵害されればすぐニュースになる |
| 著名なサードパーティ | 中程度 | メンテナのアカウント侵害リスクがある |
| マイナーなサードパーティ | 高め | 攻撃対象になりやすく、監視も少ない |
公式Actionsは「Immutable Releases」という機能でタグの改ざんを防ぐ仕組みを採用しているため、リスクは軽減されています。
とはいえ、ゼロではありません。
結局どうすればいい?ベストプラクティス
プロジェクトのセキュリティ要件に応じて、以下のように使い分けるのがおすすめです。
パターン1:セキュリティ最優先のプロジェクト
金融、医療、インフラ系など、セキュリティが最優先の場合は公式Actionsでもハッシュ指定が推奨されます。
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0パターン2:一般的なプロジェクト
多くのプロジェクトでは、このバランスで十分です。
# 公式 → タグでOK
- uses: actions/checkout@v7
# サードパーティ → ハッシュ指定
- uses: some-org/some-action@a1b2c3d4e5f6...パターン3:個人開発・速度重視
全部タグ指定でも動きますが、リスクは認識しておきましょう。
ハッシュ固定でも「そのまま動き続ける」わけではない
ハッシュで固定すれば、実行されるコードは変わりません。
ですが、そのコードを動かすランナー側は変わり続けます。
わかりやすい例が、GitHub Actions のランナーから Node.js 20 が削除される期日である 2026 年 9 月 23 日です。
actions/checkout@v4 と actions/setup-node@v4 は action.yml の runs.using が node20 のため、この日を境に起動しなくなります。
タグで v4 を指していても、v4 のコミットハッシュで固定していても結果は同じです。
つまりハッシュ固定が守ってくれるのは「中身のすり替え」だけで、ランタイム廃止のような外部環境の変化には無力ということです。
固定する以上は、更新を検知する役割を別に用意しておく必要があります。
補足:Dependabotを活用する
どちらの方式でも、Dependabotを有効にしておくとActionsの更新を自動で検知してPRを作ってくれます。
ハッシュ指定でも更新が楽になるので、ぜひ設定しておくことをおすすめします。
前節の Node.js 20 の件のように、放っておくと動かなくなる更新を拾えるのが最大の効用です。
まとめ
使い分けの方針を整理すると、以下のようになります。
| 方針 | 推奨ケース |
|---|---|
| 公式もハッシュ指定 | セキュリティ最優先、監査要件がある |
| 公式はタグ、他はハッシュ | 一般的なプロジェクト |
| 全部タグ指定 | 個人開発、速度重視 |
最近公式Actionsもハッシュ指定する人が増えているのは、サプライチェーン攻撃への意識が高まっているからです。
私自身は、これまで「公式はタグでいいだろう」と思っていましたが、今回調べてみて考えが変わりました。
今後はプロジェクトの重要度に応じて、公式Actionsもハッシュ指定することを検討してみようと思います。
あわせて読みたい(GitHub Actions 運用)
- PAT を GitHub App トークンに置き換える手順と 3 つの落とし穴
- GitHub Actions の cron に timezone が使えるようになった話(JST の日跨ぎ問題がついに解決)
- GitHub Actionsのschedule(定期実行)cronを日本時間で組む|cron式メーカー&次回実行チェッカー
- GitHub ActionsでPRを自動作成する方法|gh CLIへの移行と落とし穴
- GitHub Actionsの「set-output is deprecated」警告を修正する方法
- actions/setup-goで「Restore cache failed」の警告が出る時の対処法
