跳至主要內容
>_ITDITD網站資安平台

資安事件與漏洞

Codecov 竄改事件(2021)——CI 中『被信任的工具』被劫持導致機密資訊外洩的原因與防禦

2021 年,開發工具 Codecov 的「Bash Uploader」(在 CI 中以 curl|bash 方式執行的指令稿)在上游被竄改,長達約兩個月,使用該工具的企業的 CI 環境中的機密資訊(API 金鑰、權杖、認證資訊)被傳送到外部。最終發現它的,是某一家公司的總和檢查碼比對。HashiCorp、Twilio 等還發生了二次受害。本文把供應鏈攻擊的連鎖拆解為一張防禦地圖,僅憑公開記錄的事實,講解讓你的 CI 不再重蹈覆轍的具體做法(取得物的完整性檢核、CI 機密的最小權限、輪替、egress 監控)。

發布於 2026-06-07 更新於 2026-06-07 閱讀時間 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 機密的最小權限、定期輪替)無論規模大小都有效。