“Codecov不再是一个警示故事,它是模板。”这句话出自2021年那场持续了61天的供应链攻击复盘,而今天它更像是一句对现代软件构建方式的总结。
2021年1月,一名攻击者在一个被广泛使用的bash脚本里添了一行代码。随后,数万个组织在日常的持续集成流程里下载并执行了这份脚本。每一次流水线运行、每一次代码提交、每一个构建任务,都忠实地将CI运行器中的所有环境变量发送到一个陌生的IP地址。整整61天,没人察觉到异常。直到事件曝光,人们才意识到,攻击者没有攻破任何生产系统,却已拿到通往生产系统的所有钥匙。
![]()
随后的几年,印证了这并非孤例。2024年的XZ Utils后门事件,是一名维护者花费大约两年时间获取信任,最终将远程代码执行路径植入一个几乎所有Linux发行版都包含的压缩库中。它被撞破的契机,竟是一位微软工程师发现自己的SSH登录慢了半秒钟。这件事足够荒谬,但也足够真实。几个月后,polyfill.io域名易手,几天之内,一个嵌入数十万网站的脚本就变成了恶意软件分发网络。npm和PyPI仓库里被植入后门的软件包接连出现,多到已不太有人费力去数。
Codecov事件所以值得反复审视,并不在于一家公司在2021年遭遇了数月噩梦,而在于让攻击成为可能的安全模型。这种模型不是某一个供应商的独特缺陷,而是当代几乎所有软件构建流程的结构性特征。简单来说:管道才是边界,护城河不在生产环境前方,而应该围绕那个把代码部署到生产环境的系统。
过去二十年,安全架构习惯把生产环境视作城堡,把外界当作荒地。防火墙、WAF、网络分段、IAM策略大多将防护方向朝外。问题是,现代生产环境早已不是一座城堡,而是一条构建链条。代码提交变成制品,制品变成部署,部署变成运行中的基础设施,并且拥有访问客户数据库的权限。这条链条的每一环上,自动化的系统都持有凭据,其权限之高,如果不细看,几乎等同于“想做什么就做什么”。
CI运行器握有AWS密钥,构建节点持有容器注册中心的凭据,部署步骤能与Kubernetes直接对话。甚至实习生的GitHub Action,原则上可以推送到主分支。任何一个环节失守,“生产环境”与“非生产环境”的区分就只停留在字面上。每引入一个新团队、一个新工具、一次新集成,能够读取机密的实体范围就扩大一圈,而管道几乎从未获得与其交付的基础设施同等的治理。
Codecov攻击就是一个标准样本:攻击者不需要直接面对生产防火墙,只需要污染构建环节。那个被篡改的脚本原本是一段用于上传测试覆盖率的合法代码,它来自一个已被攻破的Codecov Docker镜像。镜像被替换后,管道里的每一次运行都外泄了CI环境中的所有变量。很多组织将生产凭证、签名密钥直接放在环境变量里,攻击者无需破解,直接接收。
这种攻击模式难以被传统监控捕获。因为在正常的DevOps节奏里,管道每时每刻都在执行类似的动作:拉取镜像、运行脚本、推送数据。多一行curl命令,混在大量合法的网络请求中,几乎就是透明的。XZ Utils后门也遵循了相同的逻辑——攻击者没有触碰任何用户系统,而是污染了源头,让下游自发地把它分发出去。polyfill.io的接管更是展示了供应链中单点域名控制权转移的破坏力。
当越来越多组织将安全重心放在运行时防护和云工作负载保护上时,攻击者在悄悄转向更上游。绕过生产环境的边界毫无必要,因为构建过程本身就拥有完整的生产访问权。从这个意义上看,Codecov不是事故,而是手册。它将攻击面从“怎样入侵一座堡垒”重写为“怎样获得一次构建过程的控制权”。而后者的难度,往往只是一行代码或一次依赖项更新。
相关讨论还指向一个更棘手的现实:即便知道了模版,防御也并不简单。管道的复杂性和异构性让统一治理变得成本高昂。安全团队通常不了解每一条CI流程到底拉取了什么外部依赖,开发团队则追求速度而绕过评审。而当攻击者学会以月为单位潜伏、以毫秒级的性能偏差作为掩护时,发现的门槛也被拉高了。
Codecov事件发生后的几年里,软件供应链安全已经成为产业关键词,但每当另一个后门出现在某个不起眼的开源组件里时,仍然会重演同样的剧情:管道在被默认信任,凭据在被无差别暴露,而护城河始终挖错了位置。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.