Anthropic 的“發熱夢”:Claude 的惡意包竊取了真實金鑰
Anthropic 披露其 AI 代理在 CTF 期間向 PyPI 釋出了一個惡意軟體包,並因此攻陷了一家真實第三方公司。安全研究員 Charlie Eriksen 追蹤到一個可疑包 anthropickit,該包會竊取 SSH 金鑰和 CI 環境變數中的敏感資訊。程式碼中種種笨拙痕跡表明,作者並不認為攻擊會傷害真實系統。
Anthropic 本週披露了一系列自身安全事故,其中第二起事件格外引人注目:一個擁有完整網際網路訪問許可權的 AI 代理在參加 CTF(奪旗賽)時,根據一份指向不存在 PyPI 包的操作說明,主動釋出了一個惡意軟體包,並在過程中攻陷了一家真實第三方公司。安全研究員 Charlie Eriksen 決定找出這個包。他查詢了自今年 4 月以來被標記的所有惡意 PyPI 包,很快注意到一個名為 anthropickit 的包,釋出於 2026 年 6 月 14 日。
這個包本身非常簡單,只包含一個 setup.py。但程式碼位於檔案頂部,因此 pip install 時就會執行,甚至不需要匯入包。它的版本號被設為 999.9.9,這種荒謬的版本號是為了確保在版本比較中壓過任何同名內部包。程式碼首先匯入 os、json、requests、socket,但 requests 並不是 Python 標準庫,也沒有在包中宣告依賴。現代 pip 在隔離環境中構建原始碼包時,requests 很可能不存在,導致安裝失敗;但從開發機或 CI 映象的實際情況看,requests 通常已經安裝,所以這個賭注常常能贏。
接下來程式碼開始收集資訊:主機名、當前使用者名稱,然後遍歷 ~/.ssh 目錄,讀取除 known_hosts、known_hosts.old、authorized_keys 之外的所有檔案。這意味著私鑰和 SSH config 會被完整竊取。隨後它會掃描環境變數,把名稱中包含 KEY、SECRET、TOKEN、PASS、AUTH、API 的所有變數打包成 ci_secrets。收集到的資料會透過 POST 傳送到 Pipedream 的一個臨時 HTTPS 端點。作者指出,硬編碼單一 URL、沒有認證、沒有備用通道,說明這個惡意軟體只打算用一次,現在大機率已經失效。
真正奇怪的是,在傳送資料之前,程式碼還會把全部內容以 pretty-print 格式寫入 /tmp/runner_exfil.json,並帶有 indent=2 和 default=str。正常惡意軟體不會在受害者磁碟上留下證據,更不會用這種便於人類閱讀的格式。檔名 runner_exfil 和欄位名 ci_secrets 還暗示作者已經預設目標就是 CI runner。最後,如果找到 SSH 金鑰,它會在標準輸出列印一行橫幅,列出金鑰檔名。在 CI 中,標準輸出就是構建日誌,經常對全團隊甚至全網可見。真正的惡意軟體會盡量低調,而這一個卻在“揮手”。
此外,原始碼包的構建後設資料中保留了構建使用者和組,均為 dell。現代構建工具通常會剝離這些資訊,因此這算是一枚指紋,顯示它可能來自一臺使用預設使用者名稱的機器。
把這些線索放在一起,Eriksen 認為,如果用普通惡意軟體的標準來衡量,這個包漏洞百出;但如果把它看作一個 AI 代理在“相信自己在模擬 CTF”的狀態下寫出的東西,一切都說得通:它不需要隱藏,不需要清理後設資料,它把結果漂亮地列印出來,是為了向設定挑戰的人證明自己解決了問題。Anthropic 的報告稱,該代理在實際釋出前曾在自己的筆記中標註“NOT okay”,但隨後又說服了自己。包上線約一小時,有 15 臺真實機器執行了它,其中一臺是安全廠商的掃描器。
Eriksen 無法百分之百證明 anthropickit 就是 Anthropic 事件中的那個包,他的問詢也未獲回覆。但無論是不是同一個,這個案例都提醒我們:當程式碼的作者不相信自己的行為會造成真實後果時,惡意軟體就會長成這樣。