安全事故与漏洞

Codecov 篡改事件(2021)——CI 工具被篡改导致机密信息外泄的原因与防御

2021 年,Codecov 的 Bash Uploader 在上游被篡改约两个月,使用它的企业 CI 中的 API 密钥和令牌被发送到外部。讲解完整性校验、CI 机密最小权限、轮换与 egress 监控等防御。

发布于 2026-06-07 更新于 2026-10-05 3 分钟阅读
本页目录

我们以「在你的环境中如何防御」的视角来解读真实发生过的公开事故,而不是把新闻重播一遍。本文是 基于公开记录(官方事后分析、CISA、安全企业的分析)的讲解。出处在文末注明。

约两个月
未被察觉的时间
〜29,000
可能受影响的客户数
SHA 比对
唯一的检测手段
二次受害
HashiCorp/Twilio 等
事故摘要 / CASE FILE
对象
Codecov(代码覆盖率测量工具)及其使用企业的 CI
公布
2021 年 4 月 15 日(篡改始于 1 月 31 日/发觉于 4 月 1 日)
手法分类
供应链攻击(对被信任的分发物进行上游篡改)+窃取 CI 机密信息
影响规模
Codecov 的大量客户(最多约 29,000)。HashiCorp、Twilio、Rapid7 等发生二次受害
根本原因
CI 未校验取得物就执行 + 分发源密钥管理不当 + CI 机密过度暴露
主要对策
取得物的完整性校验、CI 机密的最小权限、轮换、egress 监控

发生了什么(通俗版)

很多开发团队会在测试自动执行环境(CI)里,用 curl … | bash 这样的方式把外部工具取下来直接执行。Codecov 的 Bash Uploader 就是这样一个脚本。

攻击者利用 Codecov 一侧分发机制的缺陷,改写了被分发的脚本本体,让它在 CI 中执行时,把该环境里的环境变量(机密信息)发送到外部的服务器。从使用方看来,不过是像往常一样调用了被信任的工具而已。由于自己的代码一行都没变,几乎找不到察觉异常的线索。

约两个月后,某家使用企业把脚本的 校验和(SHA256)与官方的值进行了比对,发现了不一致。篡改就是这样被发现的。可能外泄的信息里包含云的密钥、部署密钥、API 密钥、令牌等,并由此连锁引发了对 HashiCorp、Twilio 等其他公司的二次受害。

自己的代码没有变化,所以很难察觉

供应链攻击瞄准的不是你写的代码,而是你信任并引入之物。所以无论是代码审查还是日志都很难察觉。人们往往不去校验自己信任的工具,而这正是攻击者利用的弱点。

攻击的各个阶段与拦截方法

重要的是,这是一条四步的连锁,而 每一步都有可以阻断的地方。请不要把它读作攻击步骤,而要读作在哪里本可以拦下。

① 用 curl | bash 执行被信任的工具(未校验内容)

⊘ 阻断点:固定取得物+校验和验证 / vendoring

↓

② 该分发物在分发源(上游)被替换

自己的代码毫发无损,所以无从察觉。

⊘ 阻断点:与已知良好的哈希比对、使用固定版本

↓

③ CI 内的环境变量(机密、密钥、令牌)被发送到外部

⊘ 阻断点:把 CI 机密收紧到最小权限、按步骤限定(不要把全部 env 都传过去)

↓

④ 用偷来的密钥向生产环境、其他服务波及二次受害

⊘ 阻断点:密钥的定期轮换+egress(外向通信)监控

每一步都本可以被拦住:校验引入之物、限定机密、定期轮换、监控外向通信。

已公布的时间线

  1. 2021-01-31

    Bash Uploader 的篡改开始(此后断断续续)。
  2. 2021-03〜

    使用企业的 CI 中的机密信息持续被发送到外部(无人察觉)。
  3. 2021-04-01

    某客户发现校验和不一致并上报。
  4. 2021-04-15

    Codecov 正式公布。建议使用企业全面更换机密。
  5. 2021-04〜

    HashiCorp、Twilio、Rapid7 等的二次受害陆续查明。Codecov 后来废弃了 Bash Uploader。

根本原因:不止一个失误

如果以「都怪 Codecov」收场,就会重演。在使用方这一侧,也 缺失了多道防御。

失守的配置(事故时)

  • CI 未校验取得物就执行(把 curl | bash 全凭信任)
  • CI 机密过度暴露(所有步骤都能看到全部环境变量)
  • 机密的轮换很少(被偷的密钥长期有效)
  • 不监控 CI 的外向通信

守住的配置(防止重演)

  • 取得物采用固定版本+校验和验证,或自行引入(vendoring)
  • CI 机密以最小权限、只在必要的步骤传递
  • 机密定期轮换(即便泄露也让寿命很短)
  • 监控 CI 的 egress,检测向陌生目的地的发送

即使是信任的工具,也要校验

供应链攻击瞄准依赖库、CI 工具、构建镜像等「信任并引入之物」。XZ Utils 事件也是同一种结构。把信任最小化,并对引入之物的完整性进行机械化校验,才是正解。

在你的环境中如何防止重演

下面是无论规模大小都有效、按优先级排序的对策。把 CI 信任并执行的东西列出来一次,就能看清哪里与你有关。

1

校验取得物的完整性(不要把 curl|bash 全凭信任)

若要在 CI 中引入外部脚本或二进制,请把固定版本(版本/提交固定)+校验和(SHA256)比对作为必须项。可能的话就引入到自己的仓库(vendoring)。这次的检测,靠的也正是这种比对。

2

把 CI 的机密最小权限化、按作用域限定

不要把全部环境变量传给所有步骤。只把需要的机密传给需要的作业、步骤。使用短命令牌(OIDC 等),减少长期密钥的常驻。

3

定期轮换机密

即便被偷,寿命短则受害有限。把定期轮换做成机制,一旦有供应链事件被报道就立即轮换。

4

监控 CI 的外向通信(egress)

让 CI 向陌生目的地的发送能够被检测到。即便在引入时没能发现被篡改的工具,也要留下一层能在外泄环节察觉的防线。

本站的立场:最小化信任,并加以校验

本站自身也是以用机器校验依赖与构建引入物为前提来设计的。Codecov 事件与 XZ Utils 揭示的是同一件事:「在信任」很容易变成「没在校验」,而供应链攻击利用的正是这一点。减少信任,对引入之物的完整性进行机械化确认。

出处(公开记录)

本文的事实基于以下公开信息。不涉及攻击的复现步骤与篡改代码,只聚焦于防御的教训。

  • Codecov 官方「Post-Mortem / Root Cause Analysis (April 2021)」— about.codecov.io
  • Codecov 官方「Bash Uploader Security Update」— about.codecov.io
  • CISA「Codecov Releases New Detections for Supply Chain Compromise」(2021) — cisa.gov
  • Rapid7「Analysis of the Codecov Supply Chain Compromise」(2021) — rapid7.com

接下来阅读

FAQ

QCodecov 事件的根本原因是什么?
A

并不是自己代码的 bug,而是『在 CI 中信任并执行的外部工具(Codecov 的 Bash Uploader),在分发源(上游)被篡改了』。CI 只是用 curl 把那个脚本取下来、未校验内容就直接执行,于是被篡改的版本照常运行,CI 内的环境变量(机密信息)被发送到了外部。

Q为什么约两个月都没能察觉?
A

因为被篡改的是别家的工具。自己的仓库和代码都没有被改动,日志里也没有出现明显的异常。最终能够发现,是因为某家使用方把脚本的校验和(SHA256)与官方值进行了比对,找出了不一致。

Q小规模开发也有关系吗?
A

有。用 `curl … | bash` 把工具引入 CI 的做法在个人开发中也很常见,如果脚本在分发源被篡改,只需执行一次,CI 的机密就可能被发送出去。本文的对策(取得物的固定+校验和验证、CI 机密的最小权限、定期轮换)无论规模大小都有效。