CI 缓存里塞了个恶意文件,你整条流水线都在替它跑——GitHub Actions 这次用 cache-mode 把权限收回来了

你有没有想过,CI 跑得快,靠的那份缓存,其实是整条流水线里最容易被动手脚的地方?

一条 pull_request_target 触发的工作流,默认就能往缓存里写东西。攻击者只要提交一个 PR,让 job 把带毒的 node_modules 或构建产物存进缓存,你后面那条完全可信的 push 构建一旦 restore,跑的就是别人准备好的代码。缓存从「加速手段」瞬间变成了「供应链入口」。

9 月 10 日,GitHub Actions 上线了 cache-mode,并已 GA 到所有套餐。它做的事情很直接:把缓存的读、写权限拆开,按 workflow / job 粒度显式授权。一句话结论——从此「谁能写缓存」不再由事件类型默认决定,而是由你在 YAML 里写清楚。

四个值,把缓存权限说透

cache-mode 一共四个取值,语义很干脆:

  • read:允许 restore,禁止 save。低信任事件(如 pull_request_target)的默认值。
  • write:允许 restore 和 save。可信事件(如 push)的默认值。
  • write-only:允许 save,禁止 restore。
  • none:完全切断缓存访问。

配置位置很灵活,workflow 级或 job 级都行,job 级覆盖 workflow 级

name: build
on: pull_request_target
jobs:
  validate:
    runs-on: ubuntu-latest
    cache-mode: read   # 只读,绝不碰缓存写入
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: ~/.npm
          key: npm-${{ hashFiles('package-lock.json') }}

这个模式下,即便 job 里误调了 save,缓存服务也会直接拦掉——被拦的 restore 当成 cache miss,被拦的 save 静默跳过,流水线不会因此挂掉。它不改变你的构建逻辑,只是把越权操作变成 no-op。

三个容易被忽略的细节

第一,模式会穿透 reusable workflow。 调用方给到的权限就是上限,被调用 workflow 拿不到更多的缓存访问。如果它硬要,GitHub 会在 run 开始前直接拒绝。但这里有个坑:如果调用方既没显式设置、也没继承 cache-mode,被调用的 reusable workflow 可以自己申请 write——哪怕触发事件本该默认只读。所以想守住只读边界的团队,必须在调用处显式声明 cache-mode: read

第二,显式声明会覆盖安全默认。 你在 pull_request_target 上写了 writewrite-only,就等于盖掉了原本的只读保护。GitHub 会在这种时候给一条 warning annotation,但不会阻止你——风险是你自己担的。

第三,你能在运行期查到实际生效的模式。 环境变量 ACTIONS_CACHE_MODE 会暴露当前 job 的有效值,用它来排查「为什么这次缓存没存上」比翻文档快得多:

- name: Show effective cache mode
  run: echo "cache mode=$ACTIONS_CACHE_MODE"

怎么落到你现在的仓库

不用一次性全改。先按「这个 job 到底需要什么」来定:

  • 只消费缓存的校验 job → read
  • 可信的缓存维护 / 构建 job → write
  • 只负责产出缓存、不需要读旧缓存的专用 job → write-only
  • 压根用不上缓存的 job → none

再记住几条缓存卫生的老规矩:别把 secret、token 塞进缓存路径;把 restore 回来的内容当成不可信输入看待;缓存 key 尽量带 OS、运行时、依赖锁文件;同仓里信任级别差很多的工作流,缓存边界要分开审。

最后一句提醒:cache-mode 让写权限在配置里显式可见了,但它不替代缓存内容本身的治理。一个缓存之所以有用,正是因为后一次运行愿意信任它——也正因如此,写权限才值得你多看一眼。

参考来源:GitHub 官方 Changelog(9 月 10 日)、GitHub Docs 工作流语法 cache-mode / 依赖缓存文档、daily.dev、DEV Community、C# Corner 实战分析。

评论区

0 条评论

登录后可评论。