配了三年 CI/CD,今天才发现 GitHub Actions 的「安全光环」从来就没罩住过 OIDC token——2026 版七步加固指南

配了三年 CI/CD,今天才发现 GitHub Actions 的「安全光环」从来就没罩住过 OIDC token——2026 版七步加固指南

OIDC token 能在 runner 内存里被抽走,这件事你知道吗?2026 年 5 月,攻击者用六分钟在 42 个 @tanstack/* npm 包里发了 84 个恶意版本,全部带着 TanStack 自有签名和有效 SLSA 凭证。武器是一枚从 CI runner 内存里提取的 GitHub Actions OIDC token,攻击路径是 pull_request_target 错误配置加缓存投毒。这件事没有砸开 TanStack 的金库——它直接劫持了整条流水线。

这不是孤例。GitHub Actions 已经成为现代软件供应链最受攻击的层面:2025 年 3 月 tj-actions/changed-files CVE-2025-30066 影响了 23000+ 仓库;2026 年 3 月,攻击者对 76 个 trivy-action 版本标签中的 75 个做了 force-push;2026 年 2 月,一个 AI 驱动的机器人在七天内系统性扫描公开仓库的可利用 CI/CD 模式,同时发起攻击。

你也许觉得这些是「大厂才有的烦恼」。但 AI 自动化扫描已经把攻击门槛降到了零——可利用的 workflow 错误配置现在会被自动发现、自动利用,不用等攻击者手动来找。

问题出在哪

GitHub Actions 的 OIDC 集成被设计成「更安全」:不用存长期密钥,云提供商发短期令牌,凭证不落地。理论上很好。但实际有三个常见的致命疏漏:

第一,OIDC 信任策略里用了通配符。攻击者只要让一个 workflow 跑起来,就能用这个 token 顶替其他仓库或其他分支的身份。2026 年 4 月 GitHub GA 的 Immutable Subject Claims 解决了这个问题,但前提是你迁移到了新格式。

第二,id-token: write 权限被放在了 workflow 级别而不是 job 级别。结果是任何触发 workflow 的事件都能请求 OIDC token,包括来自 fork 的 pull request。正确的做法是只在需要云访问的 job 级别授权,只对受信任的事件(push 到 main)开放。

第三,缓存 key 用的是分支名或 PR 号,而不是文件内容的 hash。恶意 PR 可以污染 base branch 的缓存,下一个 workflow 跑的时候就会拿到被投毒的依赖。

七步修复

第一步:收紧 OIDC 信任策略到精确的仓库、分支和 workflow 路径。不用通配符,用 GitHub 2026 年 4 月 GA 的 Immutable Subject Claims,这让它在密码学层面被强制执行。

第二步:id-token: write 只授权到 job 级别,只给真正需要云访问的 job,只在受信任事件(push 到 main,不是来自 fork 的 PR)触发时开放。

第三步:OIDC token 不要离开 runner。用 azure/login 或 google-github-actions/auth 时,确保云访问令牌只存在 runner 内存里,不写入日志、不写入 artifacts、不进入后续 step。

第四步:缓存 key 必须用内容 hash 而不是分支名。用 ${{ hashFiles("**/package-lock.json") }} 而不是 ${{ github.ref }},不要让 fork PR 和 base branch 共享缓存。

第五步:发布 job 必须走 GitHub Environment 加环境保护规则。要求人工审批、限制可部署的分支,攻击链里没有这一层的话整个链路是畅通的。

第六步:CI 里跑 actionlint,检测 pull_request_target + checkout、缺失 SHA pin、权限过大、表达式注入这些常见漏洞模式。把它设成修改 workflow 文件 PR 的必过检查。

第七步:secret scanning 的 push protection 现在默认覆盖更多模式。2026 年 8 月新增了 Lovable Labs、PostHog、Cohere、Cloudflare 等多个 provider 的检测,覆盖范围在持续扩大。免费公开仓库已经自动开启,有能力的团队应该把 push protection 扩展到私有仓库。

怎么判断自己的 pipeline 是不是已经漏了

如果你在用 OIDC 做云部署,先检查这几件事:workflow YAML 里的 id-token: write 是在 workflow 级别还是 job 级别;云端的信任策略里有没有通配符;缓存 key 里有没有用分支名或 PR 号;发布流程有没有经过 GitHub Environment 保护。这四个问题每一个答「是」都意味着攻击面。

下一步

今天的现实是:GitHub Actions 攻击已经是自动化的、规模化的,不再是「大厂专属风险」。但防护也是现成的——OIDC 本身没问题,问题在于配置。只要把信任策略写精确、把权限收窄到最小范围、把 token 留在 runner 内部,这条攻击链就断了。

如果你管着团队的 CI 安全,把这篇发给负责 GitHub Actions 配置的同学。不是选做题,是必修课。

评论区

0 条评论

登录后可评论。