GitHub Actions 安全指南为何持续收紧工作流权限
来源:17golang原创
时间:2026-10-08 21:45:55 150浏览 收藏
GitHub Actions 的安全指南持续收紧,不是因为某一个 YAML 语法突然变得危险,而是工作流已经从“自动跑测试”升级为同时掌握源码、缓存、制品、发布权限和外部云身份的供应链入口。2026 年 GitHub 连续把限制扩展到 Action 白名单、不可信触发器的缓存写入、触发者与事件规则,以及 pull_request_target 的默认保护,说明平台正在把最小权限从令牌配置推进到完整执行链。
GitHub 官方地址:https://github.com/
Actions 安全参考:https://docs.github.com/en/actions/reference/security/secure-use
- 谁能触发、什么事件能触发,开始由仓库外部的策略统一约束。
- 不可信触发器不再默认拥有同等缓存写入能力,缓存也被视为供应链资产。
GITHUB_TOKEN继续强调 job 级最小权限,而不是给整条流水线一组宽权限。- 第三方 Action、长期云密钥、自托管 Runner 和工作流文件变更都进入同一套威胁模型。
2026 年的几个变化串起来看更清楚
我第一次认真清理 Actions 权限时,只盯着 permissions。但把 GitHub 2026 年的官方更新放在一起看,会发现平台关心的已经不只是令牌读写范围。
| 官方变化 | 它控制的对象 | 反映出的安全判断 |
|---|---|---|
| 2 月:Action 白名单扩展到所有计划类型 | 允许使用的 Action 和可复用工作流 | 依赖来源应由策略限定,不能完全交给每份 YAML |
| 6 月:不可信触发器对默认分支缓存只读 | Actions 缓存写入 | 缓存可以跨信任边界传播被污染内容 |
| 9 月:工作流执行保护正式可用 | 触发者、触发事件和具体工作流文件 | 高风险工作流应在运行前被组织级策略拦截 |
| 持续更新:令牌权限细分 | GITHUB_TOKEN 的资源范围 | 每个 job 只拿完成任务所需的能力 |
这条路线的共同点是:安全控制逐渐从工作流文件内部移到更难被同一提交修改的位置。攻击者即使能改 YAML,也不应自动获得触发权、缓存写入权和部署凭据。
权限收紧的起点已经不只是 GITHUB_TOKEN
官方安全文档明确提醒,pull_request_target 和 workflow_run 在处理不可信拉取请求代码时可能进入特权上下文;它们可能接触主分支共享缓存、仓库写权限或引用的 Secrets。第三方 Action 也能通过 github.token 间接访问 GITHUB_TOKEN,即使 YAML 没有显式把 Token 作为参数传入。

2026 年 6 月的只读缓存变化很能说明问题:以前某些外部人员可触发的事件可以向默认分支作用域写缓存,后续受信任的 push 或 schedule 工作流再恢复这些缓存,就可能形成缓存投毒链。现在满足“不可信触发”和“共享默认分支作用域”两个条件时,缓存令牌只读;恢复仍可进行,但保存会被拒绝并记录警告。
这也是为什么“没有把 Secret 打印出来”远远不够。攻击面还包括缓存、工作目录、制品、Docker Socket、自托管 Runner 上的持久状态,以及一个 job 留给另一个 job 的文件。
先把令牌权限拆到 job,而不是停在 workflow
最容易落地的改造,是在工作流顶层设置只读基线,再让少数 job 单独申请额外权限。GitHub 官方建议默认让 GITHUB_TOKEN 只读仓库内容;未列出的权限会按规则落到 none,因此要把实际需要写入的资源写清楚。
name: build-and-deploy
on:
push:
branches: [main]
# 整条工作流默认只允许读取仓库内容。
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
# 示例使用官方 Action;第三方 Action 在生产中应固定完整提交 SHA。
- uses: actions/checkout@v4
- run: npm test # 示例:测试任务不需要仓库写权限。
deploy:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # 只允许申请 OIDC 令牌,不等于获得云资源写权限。
steps:
- run: ./scripts/deploy.sh # 云端权限仍由 OIDC 信任策略决定。
上例用版本标签保持可读性,但生产环境若使用第三方 Action,官方更推荐固定到完整提交 SHA,因为标签可以被移动。可以再配合 Dependabot 更新 Action 引用,把“不可变引用”和“持续更新”同时保留。
id-token: write 经常被误解。它只允许工作流向 GitHub 的 OIDC 提供方请求令牌,不会直接授予云资源写权限;真正能访问哪些云资源,仍由云平台信任条件、受众、仓库、分支、环境等声明约束。相比长期保存云密钥,短期 OIDC 身份能显著缩短泄露后的可利用时间。
不可信触发器要和特权部署彻底分开
我更倾向于把来自 Fork 的验证工作流看成“读取并测试不可信代码”,把发布工作流看成“操作受信任资产”,两者不共享写权限和长期凭据。尤其要避免在 pull_request_target 中检出并执行来自 Fork 的代码。
GitHub 在 2026 年 9 月宣布工作流执行保护正式可用,管理员可以按 actor、event 和工作流文件路径设置规则。高风险的 deploy.yml 可以只允许指定团队触发,而普通 CI 继续服务贡献者;evaluate mode 还能先观察哪些运行会被拦截,再决定是否强制执行。同期官方也开始为 pull_request_target 滚动提供默认保护。
如果暂时没有组织级执行保护,至少先做三件事:
- 外部拉取请求只运行无 Secret、只读 Token 的构建与测试。
- 部署只接受受保护分支、人工批准或明确受信任的事件。
- 缓存保存放在受信任的
push工作流中,不让不可信上下文更新共享缓存。
现有流水线可以按六层顺序收紧

- 触发者与事件:盘点
pull_request_target、workflow_run、workflow_dispatch等入口,明确谁可以触发。 - 工作流文件范围:对发布、签名、制品上传等高权限文件单独设策略,并用
CODEOWNERS要求指定人员审查。 - job 级权限:顶层只读,只有创建 Issue、发布包或申请 OIDC 的 job 才增加对应权限。
- 依赖来源:限制允许的 Action 和可复用工作流;第三方依赖固定到完整提交 SHA,并持续更新。
- 外部身份:用 OIDC 换取短期且范围受限的访问令牌,删除不再需要的长期云密钥。
- 审计回路:用 CodeQL 检查易受攻击的工作流模式,查看组织审计日志中的 Secret、策略和权限变更。
这六层没有要求一次完成。对多数团队,最划算的顺序是先降 GITHUB_TOKEN,再隔离不可信触发器,然后清理第三方 Action 与长期密钥,最后把规则提升到组织级。
失败处理也应该成为安全控制的一部分
工作流加固后,最常见的反馈不是“更安全”的提示,而是某个步骤突然收到 403、缓存无法保存或部署身份交换失败。不要第一时间把权限改回 write-all,而应把失败当成权限需求的观测信号。
| 失败现象 | 优先检查 | 不要立即做什么 |
|---|---|---|
| API 返回 403 | 失败 job 实际访问的资源和对应权限名 | 不要给整个 workflow 写权限 |
| 缓存只恢复不保存 | 触发事件是否属于不可信上下文 | 不要让外部触发器写默认分支共享缓存 |
| OIDC 无法换取云令牌 | 云端信任条件、受众、分支和环境声明 | 不要退回永久云密钥作为长期方案 |
| Action 被策略拒绝 | 来源是否在白名单、引用是否固定 SHA | 不要放开所有第三方 Action |
通知也要分层:普通测试失败发给提交者;权限策略命中、工作流文件变更、Secret 变更和发布身份异常应进入安全或平台团队能看到的渠道。GitHub 的组织审计日志可以记录相关 Actions 与 Secret 事件,适合做周期复盘。
我的判断:这是从“配置建议”走向“平台强制”
早期的 GitHub Actions 安全更多依赖维护者记住最佳实践:手写 permissions、避免危险触发器、审核第三方 Action。2026 年的变化则明显把这些经验变成平台层规则:不可信缓存默认只读、触发执行可以被策略拦截、高风险事件获得默认保护、Action 白名单覆盖更多计划。
对小型私有仓库,这种收紧会增加一点配置成本;对开源项目、包发布仓库和多团队组织,它换来的却是更明确的信任边界。真正值得优先处理的,不是 YAML 是否看起来简洁,而是一个外部贡献者能否借由触发器、缓存或第三方依赖一路触达仓库写权限和部署凭据。
常见问题
所有工作流都要设置 permissions 吗?
建议显式设置。即使新仓库默认更保守,旧仓库、组织继承设置和不同 job 的需求仍可能不同;显式权限更容易审查和迁移。
pull_request_target 完全不能用吗?
不是,但它只应在确实需要基础仓库特权上下文时使用,而且不能检出并执行不可信拉取请求代码。能够用普通 pull_request 或隔离后的 workflow_run 完成时,优先选择风险更低的结构。
固定完整 SHA 会不会让升级很麻烦?
会增加维护动作,但可以交给 Dependabot 提交更新请求,由维护者审查来源与变更。标签更方便,却不具备同等级别的不可变性。
自托管 Runner 为什么风险更高?
GitHub 托管 Runner 通常是临时且隔离的虚拟机,自托管 Runner 可能保留文件、凭据和网络访问能力。官方文档提醒,公共仓库通常不应让不可信工作流使用自托管 Runner;即使采用一次性注册,也要确保底层环境真正干净。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
科技周边 · 业界新闻 | 3小时前 | vs code · AI编程 · 业界新闻 · 开发者工具 · Copilot Codex Claude 开发流程 VS Code AI代理 Agent Host 代理会话478 收藏
-
287 收藏
-
321 收藏
-
180 收藏
-
182 收藏
-
224 收藏
-
科技周边 · 业界新闻 | 1天前 | 开发工具 · google · ai agent · 智能体 WebMCP Google I/O 2026 Antigravity Managed Agents385 收藏
-
156 收藏
-
376 收藏
-
306 收藏
-
203 收藏
-
科技周边 · 业界新闻 | 1天前 | go · 工具链 · 业界新闻 · 版本升级 · 语言特性 · Go工具链 Go 1.26 go fix Green Tea GC Go升级 new(expr) 泛型约束158 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习