配了三年 action,今天才发现它们的版本从来没被真正锁过——这件事被 Workflow Dependency Locking 彻底变了
npm 有 package-lock.json,Go 有 go.sum,Rust 有 Cargo.lock——但你的 GitHub Actions 工作流,从第一天起就用着随时会被篡改的 mutable tag。2026 年 8 月,GitHub 把这件事彻底变了。
三个真实事件,23 万仓库的中招记录
这件事不是理论风险。过去 15 个月,三次供应链攻击证明了 mutable tag 的破坏力:
- tj-actions/changed-files(2025-03):维护者账号被入侵,恶意代码把 CI 里的密钥直接打印到构建日志,23,000+ 个仓库受影响
- trivy-action(2026-03):攻击者强制推送 75 个版本标签,把凭证窃取 payload 注入 10,000+ 下游工作流,流水线还显示执行成功
- actions-cool(2026-06):标签被重定向到一个根本不在任何分支历史里的「仿冒提交」,从 runner 内存里直接拖走凭证
三次事件的模式完全一样:mutable tag → 静默替换 → 零感知 → 凭证到手。而所有用 commit SHA 固定的流水线,在三次事件里全部免疫。
Workflow Dependency Locking 是什么
GitHub 在 2026 年 8 月把工作流依赖锁定推进了技术预览,本质是给 CI/CD 流水线加一个 lockfile。新增 dependencies: 段落,直接写在 workflow YAML 里,记录每个 action 的 commit SHA + 密码学哈希:
dependencies:
actions/checkout:
commit: b4ffde65f46336ab88eb53be808477a3936bae11
ref: v4.3.1
hash: sha256:a1b2c3...
actions/setup-node:
commit: 1d0ff469b1e4680f35b1f8cd5c4e6a8f5d1e3b2a
ref: v4.1.0
hash: sha256:b2c3d4...
运行时 SHA 对不上?跑都不让你跑——校验发生在 job 执行之前,不是中途,不是一堆日志写完才发现。
ref 字段保留了人类可读的版本号,reviewer 能同时看到「你要什么」和「实际跑了什么」,每次变更都以 PR diff 形式出现,没有任何静默更新。
现在怎么用
gh-actions-pin 这个 CLI 扩展帮你生成和维护 dependencies: 段落,你继续用 @v4 写代码,它来处理 SHA 解析:
gh extension install gjtorikian/gh-actions-pin
gh actions pin # 生成或更新 lockfile
gh actions pin --verify # 加到 CI 里检测篡改
Dependabot 集成在规划里,等它落地后 Dependabot 会自动开 PR 更新陈旧的锁定 SHA——和现在 npm/Cargo 的体验一样。
和手动 SHA pinning 有什么区别
你当然可以手动把所有 @v4 换成 40 位 SHA,但没有工具强制、没有传递依赖追踪、没有自动化新鲜度检查。Workflow Dependency Locking 把这些全自动化了,还加了哈希校验。手动 pinning 是临时方案,这是结构性的修复。
如果你已经在用 StepSecurity Harden-Runner 或第三方 gh-actions-lockfile action,这些仍然有意义——它们管的是运行时监控和策略执行,和 lockfile 管的是不同层面,两者是互补关系。
下一步:现在能做什么
正式 GA 目标 2026 年 9-12 月,在此之前:
- 立即列出高风险工作流:处理部署凭证、生产密钥、云访问的工作流,优先级最高
- 手动 SHA pinning:在 GA 之前,用
@sha1格式替代所有@tag,尤其第三方 action - 申请技术预览:GitHub Community Discussion #194494 开放申请,早进去早用上
- runner 版本检查:自托管 runner 需要 2.336.0+ 才能支持新语法
- 把这个放进安全审计清单:CI/CD 供应链审计要把 action 版本锁定列为必检项
npm 用 lockfile 用了十年,CI/CD 终于跟上了。这件事不是要不要跟的问题——是早跟上早安心。
评论区
登录后可评论。