> ## 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 的固定与安全

> 作为对包供应链攻击的防护措施，讲解将 GitHub Actions 依赖从版本号固定到 SHA 哈希的方法，包括 Dependabot 的自动更新策略。

为应对针对 GitHub Actions 的攻击与篡改风险，官方 Laravel 项目也采用了一种安全对策——GitHub Actions 的固定（pinning）。本页面从包开发者的视角，实用地讲解应当采取的安全措施。

<Info>
  本页面是[包开发基础](/zh/advanced/package-development)的姊妹页面。前提是你已了解 GitHub Actions 的基本用法。
</Info>

## GitHub Actions 的安全风险

### 基于标签引用的隐患

通常，GitHub Actions 会像下面这样通过标签引用：

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

这种做法的问题：

* **标签可移动** — 标签可被删除后重新创建，保持同名
* **篡改风险** — 仓库所有者账号被劫持后可注入恶意代码
* **供应链攻击** — 若你依赖的 Action 被攻击，你的工作流也会受损

### 官方 Laravel 项目的做法

[laravel/laravel](https://github.com/laravel/laravel) 与 [laravel/framework](https://github.com/laravel/framework) 都将所有 Action 固定到提交哈希（SHA）。

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

## 固定的落地策略

### 第 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
* **控制更新方式** — 未固定的 Action 按版本更新，已固定的按 SHA 更新

### 第 2 步：将现有 Action 固定到 SHA

将现有工作流中所有 Action 的引用改为 SHA 哈希。可以借助 [pinact](https://github.com/suzuki-shunsuke/pinact) 等工具自动化。

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

```shell theme={null}
# 将工作流中的 Action 固定到 SHA
pinact run
```

#### 手动修改

若无法使用 `pinact`，可以在 GitHub 的 [Lookup latest version](https://github.com/actions/checkout) 页面查找每个 Action 的提交 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` 提交并推送到仓库后，Dependabot 会自动开始扫描。

## Dependabot 的自动更新机制

Dependabot 会根据 `dependabot.yml` 的配置采用不同更新策略。

### 未固定的 Action

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

Dependabot 的更新方式：**将版本范围升到新版本**。

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

这种方式偏向便捷，能应对标签的移动，但安全风险仍存在。

### 已固定的 Action

```yaml theme={null}
# 固定后
- uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
```

Dependabot 的更新方式：**升到新版本的提交哈希**。

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

这种方式最为安全。新版本仍以提交哈希引用，对篡改具有更强抵抗力。

## 工作流实现示例

以下是多个工作流共同使用 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. 确认工作流执行结果
2. 确认是否有破坏性变更
3. 合并完成

### 安全更新 PR

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

与安全修复相关的更新优先合并。

### 多个 Action 的分组更新

当在 `dependabot.yml` 中配置了 `groups` 时，多个 Action 会在同一个 PR 中一并更新。

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

把所有 Action 的更新合并到一个 PR，可减少合并次数。

## 固定的收益与代价

### 收益

| 收益          | 说明                               |
| ----------- | -------------------------------- |
| **抵御供应链攻击** | 引用具体的提交哈希，可对抗 Action 的篡改         |
| **可审计性**    | 能追踪每个 Action 何时从哪个版本更新           |
| **显式更新**    | Dependabot 会以 PR 形式提出更新，必然经过人工审核 |
| **可复现性**    | 同一提交哈希执行时，环境完全一致                 |

### 代价

| 代价           | 应对方式                          |
| ------------ | ----------------------------- |
| **初始需要手工设置** | 使用 `pinact` 工具自动化             |
| **更新管理成本上升** | 通过 Dependabot 自动创建 PR，把成本降到最低 |
| **可读性下降**    | 在注释中并列版本号以保持可读性               |

## 安全审计检查清单

在启动新包项目时可参考的检查清单。

<AccordionGroup>
  <Accordion title="初始设置">
    * [ ] 创建 `.github/dependabot.yml`
    * [ ] 将所有现有 Action 固定到 SHA
    * [ ] `pinact` 或手动核对完毕
    * [ ] 确认工作流可正常执行
  </Accordion>

  <Accordion title="定期维护">
    * [ ] 每周至少审查一次 Dependabot 的更新 PR
    * [ ] 优先合并安全相关的更新
    * [ ] 新增 Action 时务必以 SHA 引用
    * [ ] 每月检查一次全部工作流的状态
  </Accordion>

  <Accordion title="审计">
    * [ ] 确认所有 Action 引用均为 SHA
    * [ ] 确认 Dependabot 已启用
    * [ ] 确认过去 6 个月的 Dependabot PR 都已合并
  </Accordion>
</AccordionGroup>

## 相关页面

<Columns cols={2}>
  <Card title="包开发基础" icon="box" href="/zh/advanced/package-development">
    以 Service Provider 为核心讲解 Laravel 包的开发方式。
  </Card>

  <Card title="包的版本兼容性管理" icon="tag" href="/zh/advanced/package-versioning">
    应对 Laravel 主版本升级的包维护策略。
  </Card>
</Columns>


## Related topics

- [GitHub Actions - GitHub Copilot SDK for Laravel](/zh/packages/laravel-copilot-sdk/github-actions.md)
- [会话恢复](/zh/packages/laravel-copilot-sdk/resume.md)
- [打包 Copilot CLI](/zh/packages/laravel-copilot-sdk/bundle-cli.md)
- [Remote Sessions](/zh/packages/laravel-copilot-sdk/remote-sessions.md)
- [Laravel Prompts](/zh/prompts.md)
