首页/开发/CI/CD 与发布速查/缓存投毒的防护
流水线设计54 条

缓存投毒的防护

共享缓存可被写坏:限制不受信代码写缓存,隔离分支缓存作用域,对关键制品保留校验。

CI/CD 与发布速查开发更新于 2026-10-13

缓存投毒是什么

缓存投毒指共享缓存被写入不受信的内容——来自 fork 的 PR、低权限分支或被入侵的作业——后续流水线读取并复用它,轻则引入错误依赖,重则执行被篡改的编译产物,是供应链攻击的一条现实路径。除恶意写入外,也包括「键设计不当导致内容混入」的非恶意损坏。防法的核心:收紧谁能写缓存、把缓存当优化而非常识来源、关键产物在消费端做校验。

基本信息

适用平台GitLab CI、GitHub Actions、Jenkins、容器构建缓存均涉及
风险恶意或错误内容写入缓存后被后续流水线复用
缓解仅默认分支写缓存;fork/PR 只读;缓存与制品分离
验证关键产物以校验和或签名在消费端复核

典型使用场景

  • 开源仓库:fork PR 可以触发构建,但不应能写入默认分支的缓存
  • 多租户 runner:不同项目共享执行机,本地缓存目录必须按项目隔离
  • 公共依赖缓存:自建 npm/pip 镜像缓存被上游投毒后向下游扩散
  • 容器构建缓存:BuildKit/Buildx 的缓存导入必须限制来源,避免载入被篡改的层
  • 应急排查:产物行为异常时,回溯它命中的缓存条目与写入者

隔离写法示例

隔离写法示例
# GitLab:缓存键带分支 slug,天然隔离不同分支的写入
cache:
  key: "$CI_COMMIT_REF_SLUG-pip"
  paths:
    - .cache/pip
# GitHub Actions:fork PR 的缓存默认只读,不能回写默认分支缓存
# 关键:产物不进缓存,走制品库并附校验和

写入权限模型

来源可读可写
默认分支流水线是是(唯一可写来源)
受保护分支是按策略,建议受限
fork / 外部 PR仅读本 PR 缓存否
本地开发机可读否(不共享生产缓存)
把缓存当「优化」而不是「事实来源」:缓存缺失或损坏时构建仍应正确完成,只是变慢。
持久化工作目录也等同共享缓存:跑过不受信作业的 runner 若不清洗工作区,残留文件会混进下一次构建的输入,托管 runner 与自建 runner 都要把作业前清理写进流程。

易错点

  • 把编译产物只存于缓存:被投毒即影响成品,关键产物应走制品库并校验
  • 缓存键包含外部可控输入却不做校验:不同来源的内容混入同一键
  • 缓存键不含锁文件哈希:依赖升级后仍命中旧键,恢复出错误的依赖树
  • 缓存目录里留存了认证凭据(源站 token、registry 密码):随缓存被恢复或导出而泄漏

数据来源与参考

  • GitHub Docs《Dependency caching》
  • GitLab Docs《Caching in GitLab CI/CD》
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌