# GitHub Actions を SHA ピン留めして Dependabot で更新する：サプライチェーン攻撃を防ぐ実践

> GitHub Actions の `uses:` を可変タグからコミットSHAへピン留めし、Dependabot で安全に更新し続ける実践ガイド。公式のセキュリティ強化指針（2026年6月時点）に忠実に、なぜタグ参照が危険か、SHAピン留め＋バージョンコメント、Dependabot が SHA とコメントを同時更新する挙動、既存リポジトリの一括ピン留め、最小権限 GITHUB_TOKEN・信頼できるアクションのみ許可・SHA固定の強制ポリシーまで、多層防御を実コードで解説します。

- 公開日: 2026-06-28
- 著者: 友田 陽大
- タグ: Dependabot, GitHub Actions, サプライチェーンセキュリティ, DevSecOps, CI/CD, セキュリティ
- URL: https://tomodahinata.com/blog/dependabot-github-actions-sha-pinning-supply-chain-security-guide
- カテゴリ: Dependabot・依存関係の自動更新
- 総合ガイド: https://tomodahinata.com/blog/dependabot-production-guide

## 要点

- uses: actions/checkout@v4 のようなタグ参照は『可変』。タグは付け替えられるため、信頼したアクションが後から改ざんされる供給網リスクがある。tj-actions 系の事件はこの構造を突いた
- 唯一の不変参照はフルのコミットSHA。uses: actions/checkout@<40桁SHA> # v4.2.0 とし、末尾コメントで人間が版を読めるようにする。SHA衝突は現実的に困難なため監査済みコードを固定できる
- Dependabot は SHA ピン留めを理解し、新版が出ると SHA とバージョンコメントを同時に更新するPRを開く。だからピン留めしても更新は止まらない——package-ecosystem: github-actions を設定するだけ
- 多層防御：SHAピン留め＋Dependabot＋最小権限 GITHUB_TOKEN（permissions を明示）＋信頼できるアクションのみ許可（Actions ポリシーで SHA 固定を強制）。1つに頼らず重ねる
- アクションの auto-merge は慎重に。fetch-metadata の maintainer-changes を見てメンテナ交代は人間レビューへ。サードパーティ製ほど慎重、公式（actions/*）の patch は自動寄りに

---

`uses: actions/checkout@v4` ——あなたの CI のほぼすべての行が、こう書かれているはずです。けれどこの **`@v4` は“可変”**です。タグはいつでも別のコミットに付け替えられる。つまり**今日監査して信頼したアクションが、明日には別のコードに化けている**かもしれない。これが GitHub Actions のサプライチェーンリスクの核心で、過去の実際の侵害（人気アクションのタグ書き換えによる秘密情報の窃取）はまさにこの構造を突きました。

対策は明確です。**アクションをコミットSHAにピン留め（不変化）し、Dependabot で安全に更新し続ける**。この記事は[Dependabot 本番運用ガイド](/blog/dependabot-production-guide)の各論として、その実践を解説します。

> **この記事のルール**：推奨パターンは **GitHub 公式のセキュリティ強化ガイド（2026年6月時点）** に基づきます。CI のセキュリティは攻撃手法も対策も進化が速いので、本番適用前に必ず[公式の Secure use reference](https://docs.github.com/en/actions/reference/security/secure-use)で最新を確認してください。

---

## 0. なぜタグ参照が危険か

GitHub Actions の参照には3段階あり、**不変性（immutability）が違います**。

| 参照 | 例 | 不変か | リスク |
| --- | --- | --- | --- |
| メジャータグ | `@v4` | ✗ 可変 | いつでも別コミットを指せる。最も危険 |
| 完全版タグ | `@v4.2.0` | ✗ 可変 | セマンティックだが、タグは付け替え可能 |
| **コミットSHA** | `@a1b2c3...`（40桁） | ✓ **不変** | 監査済みコードに固定。**推奨** |

タグはただのポインタです。攻撃者がアクションのリポジトリを乗っ取れば、`v4` を**バックドア入りのコミット**に向け直せます。あなたは何も変えていないのに、次の CI 実行で悪性コードが走る——これが「タグの可変性」を突く攻撃です。

---

## 1. SHA ピン留め＝唯一の不変参照

対策は、**フルのコミットSHA**で固定することです。

```yaml
# Before（可変・危険）
- uses: actions/checkout@v4

# After（不変・推奨）— SHA に固定し、末尾コメントで版を可読に
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
```

なぜ安全か：

- **不変**：SHA はコミット内容のハッシュ。指す先のコードは未来永劫変わりません。あなたが**監査して信頼した瞬間のコード**に固定されます。
- **改ざん耐性**：別のコードを同じSHAに見せかけるには SHA-1 衝突を有効な Git オブジェクトで作る必要があり、現実的に困難です。
- **可読性**：末尾の `# v5.0.0` コメントで、人間は一目で版が分かります。そして**このコメントは Dependabot が更新時に書き換えてくれます**（次章）。

> 短縮SHAやタグ参照ではなく、**40桁のフルSHA**を使ってください。これが「不変なリリース」としてアクションを使う唯一の方法です。

---

## 2. Dependabot は SHA ピン留めを更新できる

「SHA で固定したら、もう更新されないのでは？」——よくある誤解です。**Dependabot は SHA ピン留めを理解します**。

新しいバージョンが出ると、Dependabot は**SHA と末尾のバージョンコメントを同時に更新するPR**を開きます。タグ参照のときと**まったく同じ更新体験**で、しかも常に**不変参照のまま**でいられます。

```yaml
# Dependabot が開くPRの差分イメージ
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ - uses: actions/checkout@<新しいSHA> # v5.1.0
```

設定は[`package-ecosystem: github-actions` を足すだけ](/blog/dependabot-yml-configuration-complete-guide#1-package-ecosystem対応エコシステム)です。

```yaml
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"           # .github/workflows/ を見る
    schedule:
      interval: "weekly"
    commit-message:
      prefix: "ci"
    groups:
      actions:
        patterns: ["*"]      # アクション更新を1PRに束ねる
```

**「不変性（SHAピン）」と「鮮度（Dependabot）」はトレードオフではなく、両立できる**——これがこの記事の最重要ポイントです。ピン留めの安全性を取りつつ、更新は自動で追いつく。

---

## 3. 既存リポジトリを一括ピン留めする

数十のワークフローを手でSHA化するのは現実的ではありません。**自動ピン留めツール**を使います。

- **`pinact`**（OSS CLI）：`uses:` のタグを解決して**フルSHA＋バージョンコメント**へ一括変換。
- **StepSecurity の Secure Workflows / Harden-Runner** などのサービスも、ピン留めと監査を提供します。

```bash
# 例：pinact でリポジトリ内のアクションを一括ピン留め
pinact run
```

導入後は **Dependabot がコメント付きSHAを維持・更新**してくれるので、一度ピン留めすれば運用は回り続けます。CI に「ピン留めされていないアクションを検出したら落とす」チェックを入れると、リグレッションも防げます。

---

## 4. 多層防御：SHA ピンだけに頼らない

SHA ピン留めは強力ですが、**単独では万能ではありません**。重ねます。

### 4.1 最小権限の GITHUB_TOKEN

ワークフローの `permissions` を**明示して絞る**。既定の広い権限を放置しない。

```yaml
permissions:
  contents: read          # 既定を絞り、必要なジョブだけ昇格する
```

万一アクションが侵害されても、**トークンでできることが小さければ被害は限定**されます。これは Dependabot の[auto-merge ワークフロー](/blog/dependabot-auto-merge-github-actions-automation-guide#3-tokenモデルここがセキュリティの肝)でも同じ原則です。

### 4.2 信頼できるアクションだけを許可

Organization/リポジトリの **Actions ポリシー**で、使用可能なアクションを制限します。GitHub は **SHA 固定を要求するポリシー**（許可するアクションをSHA参照に強制）も提供しています。「誰でも好きなアクションを `uses:` できる」状態を絞るだけで、攻撃面が大きく減ります。

### 4.3 サードパーティの監査

- **公式（`actions/*`、`github/*`）**は比較的低リスク。
- **サードパーティ製アクション**は、ピン留め前に**ソースを監査**し、スター数・メンテナンス状況・権限要求を確認。
- ピン留め後も、Dependabot PR で**メンテナ交代（後述）**を監視。

---

## 5. アクションの auto-merge は“慎重に”

アクションの patch/minor も auto-merge できますが、**サプライチェーンの観点では一段慎重**にします。理由は、アクションの更新は**CI そのものの実行コードの変更**だからです。

`dependabot/fetch-metadata` の `maintainer-changes` を使い、**メンテナが交代した更新は人間レビューへ**回します。メンテナ交代は**乗っ取りの兆候**になり得ます。

```yaml
      - name: Hold actions PRs with maintainer changes
        if: |
          steps.meta.outputs.package-ecosystem == 'github_actions' &&
          steps.meta.outputs.maintainer-changes == 'true'
        run: |
          gh pr comment "$PR_URL" --body "⚠️ アクションのメンテナ変更を検知。供給網観点で人間レビュー必須。"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Auto-merge trusted first-party action patches
        if: |
          steps.meta.outputs.package-ecosystem == 'github_actions' &&
          steps.meta.outputs.maintainer-changes != 'true' &&
          steps.meta.outputs.update-type == 'version-update:semver-patch'
        run: gh pr merge --auto --squash "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

方針：**公式アクションの patch は自動寄り、サードパーティや minor/major・メンテナ交代は人間**。リスクに比例した自動化です。

---

## 6. チェックリスト

- [ ] すべての `uses:` を**フル40桁SHA＋バージョンコメント**にピン留め（`pinact` 等で一括）
- [ ] `package-ecosystem: github-actions` を `dependabot.yml` に追加し、`groups` で束ねる
- [ ] ワークフローの `permissions` を**最小権限**で明示
- [ ] Actions ポリシーで**許可するアクションを制限**（可能なら SHA 固定を強制）
- [ ] サードパーティ製は**導入前に監査**、導入後は **maintainer-changes** を監視
- [ ] アクションの auto-merge は**公式 patch に限定**、それ以外は人間レビュー
- [ ] 「未ピン留めのアクションを検出したら CI を落とす」ガードを入れる

---

## 7. FAQ

**Q. SHA ピン留めすると更新されなくなりませんか？**
A. なりません。Dependabot は SHA ピン留めを理解し、新版が出るとSHAとバージョンコメントを同時更新するPRを開きます。不変性と鮮度は両立します。

**Q. `@v4` のままで Dependabot を使えば十分では？**
A. 更新は追えますが、**タグの可変性リスク**は残ります。タグはいつでも付け替え可能で、攻撃者が乗っ取れば `v4` を悪性コミットに向けられます。不変なのはSHAだけです。

**Q. 公式アクション（actions/checkout 等）もSHA固定が必要？**
A. リスクは相対的に低いですが、**一貫性のために全アクションをピン留め**するのが推奨です。Dependabot が更新を維持するので運用負荷は増えません。

**Q. 既存の大量のワークフローをどう変換しますか？**
A. `pinact` などの自動ツールで一括ピン留めできます。タグを解決してフルSHA＋コメントに変換し、以後は Dependabot が維持します。

**Q. アクションも auto-merge してよいですか？**
A. 公式アクションの patch は自動寄りにし、メンテナ交代（`maintainer-changes`）やサードパーティ・minor/major は人間レビューにしてください。アクション更新はCI実行コードの変更なので一段慎重に。
