LiteLLM 5 月外洩密鑰如何導致 10 月發布惡意程式版本
How a Key Leaked in May Shipped Malware in October
LiteLLM 一枚於 5 月 27 日外洩且未被撤銷的內部服務主密鑰,136 日後被用來取得 GitHub 權限,最終令含惡意程式的版本於 10 月 21 日發布至 PyPI 和 Docker。
文章沿憑證外洩、GitHub 權限擴張到發布審批鬆動,還原攻擊鏈,並指出撤銷閒置密鑰與維持雙人審批是事前可介入的控制點。
2026 年 5 月 27 日,有人不慎把一個設定檔提交到公開儲存庫。檔案內有一把主密鑰——實際上就是管理員密碼——可用來存取 LiteLLM 的其中一項內部服務。他們改寫了 Git 歷史記錄來掩蓋密鑰,之後大家便不再理會。沒有人停用這把密鑰。
這把密鑰首次在 10 月 10 日被使用,相隔了 136 天。
請仔細閲讀以下內容,因為當中沒有任何高明之處。沒有漏洞,也不是零日攻擊。每一步用到的密鑰或權杖,在不再需要後仍然有效。
攻擊鏈
LiteLLM 是一個開源閘道:你的應用程式只需與這項服務通訊,毋須直接呼叫 OpenAI、Anthropic、Bedrock 等服務。它負責路由請求、追蹤開支和管理密鑰——這亦表示它持有公司擁有的所有 AI 服務供應商金鑰。
洩漏的密鑰可解鎖一項內部工具,讓 AI Agent 提出拉取要求。攻擊者呼叫這項工具時,工具交還了一個 GitHub 存取權杖,屬於一個擁有整個組織的帳戶。沒有人限制這個權杖的權限。LiteLLM 的事後檢討報告指出,該權杖「並未與服務帳戶關聯,也沒有設限」。它可以在他們的 GitHub 帳戶中任何位置執行任何操作。
攻擊者利用這個權杖,向 LiteLLM 的主儲存庫推送了一個一次性工作。GitHub Actions 工作可以讀取儲存庫的機密資料。於是這個工作讀取了資料,並把它們傳送到攻擊者控制的網址:共六項,包括另一名維護者的個人存取權杖。另一個工作則取得第三名維護者的存取權杖。兩個工作幾分鐘後便被刪除。兩天後,另一輪攻擊又從私有儲存庫取得 14 項資料,包括 Anthropic、OpenAI 和 Bedrock 的金鑰。

每一步都使用了早已不再需要、卻仍然有效的憑證。來源:LiteLLM 事後檢討報告,2026 年 10 月 23 日。
然後,他們等了九天。
10 月 21 日,他們把 LiteLLM 的發布流程指向一個偽造的儲存庫副本:Berri-AI/litellm,中間多了一個連字號,而非真正的 BerriAI/litellm。分支保護機制擋下了這項變更,但擁有者的權杖繞過了限制。
發布版本需要兩個人:一人啟動發布,另一人核准。核准者通常使用與辦公室電腦綁定、限制嚴格的帳戶。幾天前,這項規定已放寬,任何兩名工程師都可以完成發布。攻擊者持有三名維護者的存取權杖,於是用其中一個啟動發布,再用另一個核准——LiteLLM 認為,這是為了讓稽核記錄看起來一切如常。
遭植入惡意程式碼的版本發布到了 PyPI 和 Docker。27 分鐘後,一名研究人員發現了它。PyPI 在兩小時內將它撤下。
最容易令人意外的一點
這個惡意套件安裝了三個檔案。其中一個是 cook.pth,而整件事的關鍵就在這個副檔名。
site-packages 中的 .pth 檔案通常只會列出供 Python 搜尋的額外資料夾。但它有一項幾乎沒有人會想到的舊式相容功能。如果檔案中的某一行以 import 開頭,Python 就會執行它。不是在匯入套件時執行,而是在啟動時執行。文件説明指出,這些行「總會在 Python 啟動時執行……無論某個特定模組是否真的會用到」。

以 import 開頭的 .pth 行,會在啟動時由 Python 的 site 模組執行。來源:Python 文件,site。
因此,資料竊取程式不必等到被匯入才執行。只要這部電腦上有任何 Python 程序啟動,它就會執行:無論是你的程式、測試,還是無關的專案。
包括這個:
pip install --upgrade litellm
pip 本身就是 Python 程式。執行它會啟動 Python,而 Python 會在升級修正任何問題之前,再次執行資料竊取程式。
本週應採取的措施
- 在未啟動 Python 的情況下找出檔案:
find / -name 'cook.pth' -o -name 'sitecustomize.py' 2>/dev/null。執行 pip 前,先刪除這些檔案及任何相符的.pyc檔案。 - 假設那部機器上的所有資料都已失守,不只是 AI 金鑰。資料竊取程式讀取了雲端憑證、SSH 金鑰、瀏覽器資料、資料庫 URL,以及 Codex、Claude、Gemini 和 Cursor 的設定檔。
- 按摘要值固定容器映像,而非標籤。
latest、main-latest和main-stable全都指向有問題的建置版本。 - 找出已無人需要的金鑰。這才是根本原因,也是這裏唯一可以在事故發生前採取行動處理的項目,而不是等到事故發生後才處理。
問題出在哪裏
把這件事説成「只是憑證問題」,就低估了一件事。放寬雙人規則確實造成了影響。如果核準流程仍由那部限制嚴格的辦公室電腦執行,三個被盜的權杖就不足以造成這種結果。這項控制措施確實發揮了作用,直到有人為了方便而放寬限制。
LiteLLM 表示,部分早期更新有誤,之後還會有更多變更,因此目前應把這條時間線視為至今最可靠的説法。
重點
撤銷已外洩的金鑰,不是可以留待日後處理的善後工作。這正是決定五月的一個錯誤會否在十月變成惡意軟件的關鍵。
你的基礎設施中仍在使用的最舊憑證是甚麼?如果有人使用了它,你會知道嗎?
來源
- LiteLLM 事後檢討:v1.107.0 入侵攻擊鏈 — 23 Oct 2026
- GitHub issue #47826,Upwind 研究 — 21 Oct 2026
- Socket:攻擊時間線,早 11 日的工作流程 — 23 Oct 2026
- Python 説明文件:
site模組及.pth檔案
來源:DEV Community · dev.to