> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub Actions 的 Pinning 與安全性

> 作為套件供應鏈攻擊的對策，說明如何將 GitHub Actions 相依項目由版本改為 SHA hash 進行 pinning，並包含 Dependabot 的自動更新策略。

為了因應對 GitHub Actions 的攻擊或竄改風險，官方 Laravel 專案也採用了對 GitHub Actions 進行 pinning 的安全性對策。本頁將實務地說明套件開發者應實作的安全性對策。

<Info>
  本頁為[套件開發基礎](/zh-TW/advanced/package-development)的姊妹頁。以熟悉 GitHub Actions 基本使用為前提。
</Info>

## GitHub Actions 的安全性風險

### 以 tag 為參考的危險性

一般而言，GitHub Actions 會像以下這樣以 tag 參考。

```yaml theme={null}
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
```

此方法的問題點：

* **tag 可移動** — tag 即便被刪除或重建，仍可持有相同名稱
* **竄改風險** — 若儲存庫擁有者的帳號被劫持，惡意程式碼可被注入
* **供應鏈攻擊** — 若相依的 action 遭攻擊，您的 workflow 也會受害

### 官方 Laravel 專案的對應

在 [laravel/laravel](https://github.com/laravel/laravel) 與 [laravel/framework](https://github.com/laravel/framework) 中，所有 action 都被 pinning 至 commit hash（SHA）。

```yaml theme={null}
# 安全的參考方式
- uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
```

## Pinning 的實作策略

### 步驟 1：建立 Dependabot 設定檔

於套件的儲存庫建立 `.github/dependabot.yml`。可直接複製 Laravel 的檔案。

```yaml theme={null}
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 5
    groups:
      github-actions:
        patterns:
          - "*"
```

此檔案擔負下列職責：

* **自動掃描** — 掃描 GitHub Actions 的新版本
* **自動建立 PR** — 若有更新可用，會自動建立更新 PR
* **控制更新方式** — 未 pinning 的 action 以版本更新，已 pinning 者以 SHA 更新

### 步驟 2：將既有 action 改為 SHA pinning

將既有 workflow 內所有的 action 參考改為 SHA hash。可以 [pinact](https://github.com/suzuki-shunsuke/pinact) 等工具自動化。

#### 使用 pinact 工具自動化

```shell theme={null}
# 將 workflow 內的 action 改為 SHA pinning
pinact run
```

#### 手動修改

若無法使用 `pinact`，可從 GitHub 的 [Lookup latest version](https://github.com/actions/checkout) 頁面查詢各 action 的 commit SHA，並手動替換。

```yaml theme={null}
# 變更前
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
  with:
    php-version: ${{ matrix.php }}

# 變更後
- uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
- uses: shivammathur/setup-php@0a92e4568cab5c87b7175192630661408458a086  # v2
  with:
    php-version: ${{ matrix.php }}
```

### 步驟 3：啟用 Dependabot 設定

將 `.github/dependabot.yml` commit 並 push 至儲存庫後，Dependabot 便會自動開始掃描。

## Dependabot 的自動更新機制

Dependabot 會依 `dependabot.yml` 的設定，套用不同的更新策略。

### 未 pinning 的 action

```yaml theme={null}
# pinning 前
- uses: actions/checkout@v4
```

Dependabot 的更新：**將版本範圍更新為新版本**

```yaml theme={null}
# Dependabot 建立的 PR
- uses: actions/checkout@v5
```

此方式重便利性，可對應 tag 的移動，但仍留有安全性風險。

### 已 pinning 的 action

```yaml theme={null}
# pinning 後
- uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
```

Dependabot 的更新:**更新為新版本的 commit hash**

```yaml theme={null}
# Dependabot 建立的 PR
- uses: actions/checkout@f1d3225b54b677ba3e72df8c464cb6cf6dc1aebf  # v4
```

此方式最為安全。即便為新版本，因參考的是 commit hash，故對抗竄改能力強。

## Workflow 的實作範例

以下為使用多個 workflow 中的 action 的完整範例。

```yaml theme={null}
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      fail-fast: false
      matrix:
        php: [8.2, 8.3, 8.4]
        laravel: ["^12.0", "^13.0"]

    steps:
      - uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
        with:
          fetch-depth: 0

      - name: Setup PHP
        uses: shivammathur/setup-php@0a92e4568cab5c87b7175192630661408458a086  # v2
        with:
          php-version: ${{ matrix.php }}
          extensions: dom, curl, libxml, mbstring, zip, intl, sqlite3
          coverage: none

      - name: Install dependencies
        run: |
          composer require "laravel/framework:${{ matrix.laravel }}" \
                           --no-interaction --no-update
          composer update --prefer-dist --no-interaction

      - name: Run tests
        run: vendor/bin/pest

  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4

      - name: Setup PHP
        uses: shivammathur/setup-php@0a92e4568cab5c87b7175192630661408458a086  # v2
        with:
          php-version: "8.4"
          extensions: dom, curl, libxml, mbstring, zip
          coverage: none

      - name: Install dependencies
        run: composer install --prefer-dist --no-interaction

      - name: Run static analysis
        run: vendor/bin/phpstan
```

## Dependabot 更新 PR 的處理

Dependabot 建立的更新 PR 可如下處理。

### 單一 action 的更新 PR

```
Bump shivammathur/setup-php from v1 to v2
```

此類單純的更新可依下列方式處理：

1. 確認 workflow 執行結果
2. 確認是否有破壞性變更
3. Merge 完成

### 安全性更新 PR

```
[SECURITY] Bump actions/checkout to a5ac7e51b41094c7fcab2042361574b0021804ab
```

有關安全性修正的更新應優先 merge。

### 多個 action 的分組更新

若於 `dependabot.yml` 設定了 `groups`，多個 action 會於同一 PR 中更新。

```yaml theme={null}
groups:
  github-actions:
    patterns:
      - "*"
```

將全部 action 更新集中於一個 PR，可減少 merge 次數。

## Pinning 的優缺點

### 優點

| 優點          | 說明                               |
| ----------- | -------------------------------- |
| **供應鏈攻擊對策** | 因參考特定 commit hash，可對抗 action 的竄改 |
| **可稽核性**    | 可追蹤各 action 何時、從哪個版本被更新          |
| **明確的更新**   | 因 Dependabot 以提案形式提供更新，必然經人工審查   |
| **可再現性**    | 以相同 commit hash 執行時，環境可完全重現      |

### 缺點

| 缺點           | 應對方式                      |
| ------------ | ------------------------- |
| **手動初始設定**   | 以 `pinact` 工具自動化          |
| **更新管理成本增加** | Dependabot 自動建立 PR，實作成本最小 |
| **可讀性差**     | 以註解並列版本號以確保可讀性            |

## 安全性稽核 Checklist

以下為啟動新套件專案時的檢查清單。

<AccordionGroup>
  <Accordion title="初始設定">
    * [ ] 建立 `.github/dependabot.yml`
    * [ ] 將所有既有 action 進行 SHA pinning
    * [ ] 以 `pinact` 或手動完成確認
    * [ ] 確認 workflow 可正常執行
  </Accordion>

  <Accordion title="定期維護">
    * [ ] 每週至少 1 次審查 Dependabot 的更新 PR
    * [ ] 安全性更新優先 merge
    * [ ] 新增 action 時務必以 SHA 參考
    * [ ] 每月 1 次確認所有 workflow 的狀態
  </Accordion>

  <Accordion title="稽核">
    * [ ] 確認所有 action 參考皆為 SHA
    * [ ] 確認 Dependabot 已啟用
    * [ ] 確認過去 6 個月的 Dependabot PR 是否皆已 merge
  </Accordion>
</AccordionGroup>

## 相關頁面

<Columns cols={2}>
  <Card title="套件開發基礎" icon="box" href="/zh-TW/advanced/package-development">
    說明以服務提供者為核心的 Laravel 套件開發方式。
  </Card>

  <Card title="套件的版本相容性管理" icon="tag" href="/zh-TW/advanced/package-versioning">
    說明對應 Laravel 主版本更新的套件對應策略。
  </Card>
</Columns>


## Related topics

- [TCP 模式](/zh-TW/packages/laravel-copilot-sdk/tcp-mode.md)
- [GitHub Actions - GitHub Copilot SDK for Laravel](/zh-TW/packages/laravel-copilot-sdk/github-actions.md)
- [Bot 教學 - Laravel Bluesky](/zh-TW/packages/laravel-bluesky/bot-tutorial.md)
- [打包 Copilot CLI](/zh-TW/packages/laravel-copilot-sdk/bundle-cli.md)
- [Streaming Events](/zh-TW/packages/laravel-copilot-sdk/streaming-events.md)
