一个任意文件读取漏洞,如何撬动整个 CI/CD 信任链

一、CI/CD 的安全边界不在一台服务器上

GitLab 常被当作代码托管平台,但在实际企业环境中,它更像一个交付控制平面:

复制代码
开发者身份
  ↓
代码仓库与合并审批
  ↓
GitLab CI 调度
  ↓
Runner 执行
  ↓
制品库 / 镜像仓库
  ↓
测试、预生产与生产环境

每一条箭头都代表一种信任:令牌、签名、网络身份、审批结论或制品来源。

当 GitLab 出现未认证文件读取,风险并不天然覆盖所有下游;但如果控制平面保存了能跨越这些边界的长期秘密,攻击者就可能把"读文件"变成"借合法身份操作"。


二、CVE-2026-85706 的事实范围

【已确认事实】 GitLab 于 2026 年 9 月 10 日修复 CVE-2026-85706。漏洞位于仓库提交 API,涉及路径限制不当和身份验证缺失,未认证攻击者在特定条件下可读取任意文件。

修复版本:

  • 19.1.8;

  • 19.2.6;

  • 19.3.2。

影响 18.7 起相应分支的更早版本。CISA 于 9 月 11 日将其加入 KEV,确认存在现实利用。

【证据边界】 官方没有把漏洞描述为直接 RCE、直接制品篡改或直接生产接管。本文讨论的是在额外凭据和架构条件成立时,风险如何沿 CI/CD 信任链扩散。


三、攻击链能否成立,取决于五个"如果"

如果一:服务进程可以读取秘密

文件读取能力受 GitLab 运行身份、容器挂载和文件权限限制。如果敏感凭据不在可读范围,攻击链会在第一步中断。

如果二:秘密仍长期有效

短期令牌、受众限制和来源绑定可以缩小窗口。长期静态 Token 或私钥则可能在补丁后继续有效。

如果三:秘密拥有下游写权限

只读监控令牌与能够推送镜像、修改流水线或部署生产的凭据,风险完全不同。

如果四:下游相信身份,不验证来源

如果制品库只检查"令牌是否有效",却不检查产物是否来自受信流水线,盗用令牌便可能绕过流程。

如果五:关键动作没有独立审批

当代码合并、构建、签名和生产部署都由同一身份域控制,上游被突破后就缺少第二道阻断。

因此,完整条件链是:

复制代码
文件可读
∧ 读到有效秘密
∧ 秘密有下游写权限
∧ 下游缺少来源校验
∧ 关键动作缺少独立审批
= 供应链影响可能扩大

四、四个最容易被撬动的信任点

1. Runner 身份

Runner 往往能读取 CI 变量、访问缓存和制品,并连接构建或部署环境。高风险设计包括:

  • 共享 Runner 持有跨项目永久凭据;

  • Runner 直接使用生产云 Access Key;

  • 外部合并请求可触达高权限执行器;

  • 缓存和工作目录跨项目复用。

更安全的方向是临时执行器、项目隔离、短期工作负载身份和受保护分支限制。

2. 制品与镜像身份

标签可以移动,文件名可以相同,真正可靠的是内容摘要、签名和来源证明。

如果发布系统只相信"来自某个仓库账号的推送",凭据被盗后就可能接受非预期制品。应要求:

  • 制品以摘要固定;

  • 发布产物经过独立签名;

  • 签名身份与受信流水线绑定;

  • 部署端验证签名和来源,而不是只验证仓库权限。

3. 云部署身份

长期云密钥存放在 GitLab 或 Runner 文件系统,是最典型的信任集中。

更合理的方式是让流水线通过 OIDC 等机制获得短期身份,并限制:

  • 允许的项目和分支;

  • 令牌受众;

  • 可扮演的角色;

  • 生存时间;

  • 可执行的云 API。

4. 审批与发布身份

如果同一个 GitLab 管理员既能修改代码保护规则、又能改变流水线、还能触发生产发布,那么技术上存在单点信任。

关键发布应引入独立控制面,例如生产环境审批、独立签名服务或部署平台策略。


五、一个无害模型:信任隔离如何截断扩散

下面的模型不连接任何真实系统,只展示策略判断:

复制代码
def can_deploy(token_valid, artifact_signed,
               provenance_ok, independent_approval):
    return all([
        token_valid,
        artifact_signed,
        provenance_ok,
        independent_approval,
    ])

print(can_deploy(True, False, False, False))  # False
print(can_deploy(True, True, True, True))     # True

即使攻击者获得一个有效令牌,只要部署端仍要求可信签名、来源证明和独立审批,单个身份泄露就无法直接完成生产发布。

这就是"零信任 CI/CD"的核心:不把上游认证成功等同于下游所有动作都可信。


六、从漏洞响应到 CI/CD 对账

升级 GitLab 后,应把以下对象串成一条可验证记录:

复制代码
提交 SHA
→ 合并审批
→ 流水线身份与配置
→ Runner 身份
→ 构建材料
→ 制品摘要
→ 签名与来源证明
→ 镜像摘要
→ 部署审批
→ 生产版本

任何断点都需要解释。

重点排查:

  • 不对应可信提交的流水线;

  • 流水线配置或变量异常变化;

  • 新增 Runner 或异常执行节点;

  • 制品摘要、签名和来源证明不一致;

  • 镜像标签指向发生变化;

  • 发布或部署缺少正常审批;

  • 云审计出现异常身份使用。


七、补丁与架构改造要并行

补丁解决入口

  • 升级 GitLab 到 19.1.8、19.2.6、19.3.2 或更高安全版本;

  • 运行官方检测规则;

  • 对可能暴露的秘密执行分级轮换;

  • 验证数据库迁移和所有节点版本一致。

架构改造降低爆炸半径

  • GitLab、Runner、Registry 与生产环境分属不同身份域;

  • 静态凭据改为短期工作负载身份;

  • Runner 不直接持有跨项目或生产永久权限;

  • 制品必须签名并附带可验证来源;

  • 生产部署需要独立审批和策略校验;

  • 关键操作和秘密使用进入统一审计。

漏洞修复关注"这个入口还通不通",架构治理关注"下一个入口被突破时能走多远"。


八、DevSecOps 团队的权限矩阵

可以用下面的最小矩阵检查信任是否集中:

主体 读源码 改流水线 取秘密 推制品 部署生产
普通开发者 是 受审查 否 否 否
受保护流水线 是 固定配置 短期 是 否
发布流水线 指定版本 否 短期 签名发布 需审批
部署控制面 否 否 环境身份 验证制品 是
GitLab 管理员 管理需要 管理需要 不应直接获取生产秘密 否 否

【建议】 如果某一行同时拥有修改代码、修改流水线、读取长期秘密和部署生产的能力,应优先拆分。


九、如何验证制品仍然可信

1. 从可信源码重建

在隔离环境中固定依赖和构建参数,重新生成关键制品,比较摘要和可复现结果。

2. 验证签名与来源

确认签名身份、签名时间、构建平台和输入提交均符合发布策略。

3. 检查仓库与注册表事件

关注异常推送、标签移动、删除、覆盖和权限变更。

4. 将部署记录与流水线对账

生产版本应能回溯到唯一制品摘要、可信流水线和经过审批的提交。

【边界说明】 需要进行多深的重建取决于是否存在可信命中、日志缺口和凭据暴露证据。并非所有受影响实例都必须无差别重建全部制品。


十、P0---P2 落地清单

P0:控制当前事件

  • 升级全部自托管 GitLab 节点;

  • 保全日志并运行官方检测规则;

  • 收紧公网入口;

  • 枚举 GitLab 进程可读的秘密和挂载;

  • 对可信命中启动凭据响应。

P1:确认交付链完整性

  • 检查 Runner 注册、流水线和变量变化;

  • 核验关键制品、镜像摘要与签名;

  • 将发布部署与提交、审批记录对账;

  • 轮换高风险凭据并撤销旧值;

  • 监控旧身份继续使用的行为。

P2:重构信任边界

  • 使用 OIDC 等短期身份连接云环境;

  • 按项目和环境隔离 Runner;

  • 构建、签名和部署使用不同身份;

  • 强制制品签名与来源证明;

  • 生产部署引入独立审批策略;

  • 定期演练代码平台失陷场景。


十一、不要把这些推断写成事实

"任意文件读取等于已经投毒制品"

错误。还需要读到有效身份、拥有写权限并绕过下游验证。

"CVSS 10.0 等于直接 RCE"

错误。官方披露的直接能力是文件读取,不能省略后续条件。

"没有发现异常流水线就没有泄露"

错误。攻击者可能仅收集秘密,延后或在下游使用。

"轮换 GitLab 密钥就覆盖所有下游"

错误。Runner、云平台、制品库和第三方集成可能各自维护独立凭据。


总结

CVE-2026-85706 之所以值得从 CI/CD 架构角度审视,不是因为文件读取必然导致供应链入侵,而是因为它暴露了一个长期存在的问题:太多交付系统把信任集中在 GitLab 和少数静态秘密上。

成熟的软件供应链应能做到:即使代码平台的一个边界被突破,攻击者仍无法凭单个令牌修改制品、伪造来源并部署生产。补丁解决今天的漏洞,信任隔离决定下一次漏洞的爆炸半径。

相关推荐
微软技术分享3 小时前
面向二进制安全的大模型多智能体框架
网络·安全·web安全
Nebula_g10 小时前
JavaSE拓展:可变参数
java·开发语言·算法·安全·javase·可变参数
在角落发呆10 小时前
软件配置备份方法:从手动到自动化的实践指南
windows·安全
YonyouHRSaaS11 小时前
从安全、信创、运维三方面看,人力资源管理系统哪种部署方式更适合企业HR?
运维·安全·hr系统·人力资源管理系统·hr saas·人事管理系统
白猫不黑12 小时前
网络安全专业:从入门到进阶的完整学习路线
学习·安全·web安全·计算机·网络安全·信息安全·编程
涼叶i13 小时前
反序列化漏洞
安全·开源
请输入蚊子13 小时前
CVE-2026-8260 D-Link DCS-935L缓冲区溢出漏洞 复现
网络·安全·web安全·iot
东木月14 小时前
Windows C 盘清理指南:安全删除临时文件、缓存与 Prefetch
c语言·windows·安全
. . . . .14 小时前
地理位置定位
安全
都适、隶仁ミ15 小时前
【等保加固】MySQL5.7.38
运维·服务器·mysql·安全·等保