時事筆記
殭屍快取與失竊金鑰:兩張天價帳單的原理拆解
從 BigQuery 帳單的形狀反推 Google 計費系統怎麼壞掉,順便盤點 fibon 哪些防線已經蓋好、哪一塊還空著
快速摘要:2026 年上半年兩起 Gemini API 天價帳單事件——「刪掉的快取還在計費」與「金鑰失竊 48 小時刷掉 8.2 萬美元」。表面都是帳單爆炸,故障原理完全不同;但放大災情的是同一個結構性缺陷:雲端計費是開環系統。文末對照 fibon:哪些 bug class 對我們沒有附著面、哪條防線還沒蓋。
可略過,如果:你不用任何按量計費的 LLM API,也不好奇計費系統的內臟長什麼樣。
事件一:被刪掉的快取,還在計費
2026 年 6 月 7 日,巴西開發者 Danilo Oliveira 在 Google AI 開發者論壇發出求救帖。他的系統用 Gemini 3 Flash 的文本快取(Context Caching)跑分析,6 月 6 日下午他發現帳單不對勁:關掉產生快取的腳本、用官方 REST API 確認快取列表完全清空之後,那個叫「cached text storage token hours」的計費項目依然每小時扣他超過 1,000 巴西雷亞爾。到 6 月 7 日凌晨,累計帳單 R$17,847(約數千美元)。他最後的止血手段是把整個 Google Cloud 專案的 Gemini API 服務徹底停用。
他做了一件對所有人都很有價值的事:把帳單資料匯出到 BigQuery,貼出逐小時的明細。這份數據的形狀,比任何文字描述都誠實。它分成三段:
- 前兩天(6/3–6/5 中午):每小時穩定 4–5M token·小時、20–30 雷亞爾——這是他的腳本正常運作的基線。
- 暴增期(6/5 下午起):用量開始複利式攀升,一路衝到每小時 2 億 token·小時。
- 凍結期(6/6 下午關腳本後):每小時的計費量精確卡死在 200.7142M token·小時,小數點後四位一模一樣,像鬧鐘一樣每小時扣一次,直到他拔掉整個 API。
從帳單形狀反推故障機制
要看懂這份數據,得先理解 explicit context caching 的計費模型。你把一大段文本(例如一份長文件)上傳成快取,之後的請求引用它而不必重傳——換取的代價是儲存費:快取的 token 數 × 存放的小時數。注意這跟一般 API 呼叫的本質差異:呼叫是一次性的,快取是一種「持續計費的有狀態雲端資源」,像你租的倉庫,退租之前每小時都在算錢。
所以正常情況下,刪除快取(或 TTL 到期)應該讓計費停止。從這裡開始是我的推測——三段式的帳單形狀,幾乎只有一種機制能同時解釋:
資源面和計費面是兩套各自為政的狀態。 你呼叫 cachedContents list/delete API 時,操作的是資源面的 registry;而計費走的是另一條管線——定期對「目前存放中的 token 總量」拍快照,乘上時數出帳。某個時間點開始,刪除與過期事件停止傳播到計費面:
- 暴增期 = 腳本還在建新快取,但舊快取在計費面從未消失,存量持續堆積;
- 凍結期 = 關掉腳本後不再有新增,殭屍存量定格,變成每小時固定金額的永動扣款機;
- 而最殘酷的是:使用者面 API 顯示空清單——你能看見的狀態是乾淨的,被計費的狀態你看不見、也刪不掉。
讓推測更有底氣的是:這不是第一次。2026 年 3 月,另一位開發者 Liz2k 回報過一模一樣的模式——她建了五個 TTL 只有 5 秒的測試快取,列表查詢整天都是空的,帳單卻冒出 341 萬「儲存小時」,之後每天固定燒 $36,她稱之為「無限殭屍快取」。她最後也是停用整個 API,然後觀察到一個關鍵細節:停用之後約三天,帳單被回溯修正回真實數值。也就是說,對帳(reconciliation)邏輯是存在的,但似乎只在 API 被強制斷開時才觸發。三個月內同一個 bug class 至少公開爆了兩次。
事件二:失竊的金鑰,48 小時 8.2 萬美元
第二起是今年 2 月的事,但它跟事件一拼在一起才看得到全貌。墨西哥一個三人小團隊的 Google Cloud API 金鑰外洩,2 月 11 到 12 日之間,竊賊用它狂刷 Gemini 3 Pro 的圖像與文本生成,48 小時刷出 $82,314——他們平常一個月的用量是 180 美元。團隊向 Google 求情,得到的回覆是雲端業界的標準答案:「共享責任模式(Shared Responsibility Model)」——平台保護平台,金鑰是你家的事。
金鑰外洩當然是團隊的疏失。但讓 $180 變成 $82,314 而中途沒有任何東西踩剎車的,是結構問題:
- GCP 的 Gemini API 沒有硬性消費上限。 Budget Alert 是「通知你」,不是「擋下來」——它是觀測工具,不是控制工具。對照 OpenAI 與 Anthropic 的預付額度模式:額度燒完就停,天然封頂。
- 帳單訊號滯後。 計費資料匯出延遲可達 24 小時以上,等你「看到」異常,錢已經燒完了。
- Google API 金鑰以
AIza開頭、格式固定,在公開 repo 與前端代碼裡極易被掃描工具獵到。這種金鑰本來就不是設計來當高價值認證憑證的——直到 Gemini 把它變成可以直接換算成錢的東西。
共同根因:計費是開環的
兩起事件,一個是供應商端的狀態機壞掉,一個是客戶端的憑證失守,表面毫無關係。但把災情放大一百倍的,是同一個結構性缺陷:
「花錢的速率」和「允許花錢的授權」之間,沒有閉環。
計費是非同步、最終一致的聚合管線。你能拿到的所有訊號——dashboard、預算告警、BigQuery 匯出——全部滯後數小時到數天。而在訊號滯後的這段窗口裡,沒有任何機制把「異常的花費速率」自動接回「停止授權花費」。控制理論會把這叫開環系統(open-loop):油門踩著,但沒有接回方向盤的感測器。事件一的受害者和事件二的受害者,最後都只剩同一個手動剎車:把整個 API 服務拔掉。
對 fibon 的意義
按照時事筆記的慣例,最後回到自家:這兩個 bug class,fibon 擋得住嗎?誠實的答案分三層。
第一層:殭屍快取這類 bug,對 fibon 沒有附著面——但這是運氣加選型,不是先見之明。 fibon 的 prompt cache 策略(深入剖析 C 有完整拆解)對 Anthropic 用的是隨請求走的 cache_control 斷點、5 分鐘 TTL;對 OpenAI 與 Google 走自動 prefix cache。這些機制都沒有獨立的儲存計費 SKU——fibon 從頭到尾不持有任何「持續計費的有狀態雲端資源」,所以「刪不掉的殭屍資源」這個故障類型根本沒有東西可以附著。當初選自動 prefix cache 而非 explicit caching,理由是工程簡單與夠用,不是預見了這次事故。結論先於理由正確,記一筆,不邀功。
第二層:fibon 手上有一份供應商之外的獨立帳本,這是偵測的本錢。 fibon 的觀測層(深入剖析 A)本來就把每一次 LLM 呼叫的 token 用量——包括 cache 命中數——寫進自家的 metrics。這意味著「我以為我用了多少」有一份不依賴供應商的紀錄。事件一的受害者花了三天、靠手動翻 BigQuery 才發現異常;如果有一個「自家帳本 vs 供應商帳單」的日對帳工序,這種事第二個小時就會跳告警。差別是 R$50 和 R$18,000。
第三層:金鑰防護是 fibon 架構本來就蓋好的防線。 fibon 的 API 金鑰只存在伺服器端,前端永遠不碰;跑不可信代碼的 Worker 被關在隔離網路裡,設計目標白紙黑字寫著「即使被攻破也無法觸及 API Key」(第 6 章)。事件二那種「金鑰躺在前端代碼或公開 repo 裡」的失敗模式,在這個架構下沒有發生的路徑。
最後給所有用按量計費 API 的人四道防線,按性價比排序:
- 計費層防火牆——高風險工作負載放獨立雲端專案,預算告警綁自動斷開 billing 的 function(GCP 官方文件就有這個模式,它是唯一真正的硬上限)。
- 金鑰不落地——金鑰只存在你的伺服器,前端與公開 repo 永遠拿代理端點。
- 自記帳本——自己記錄每次呼叫的用量,跟供應商帳單對帳,不要把「知道自己花了多少錢」外包給帳單系統。
- 避開持續計費的有狀態功能——除非你真的需要 explicit caching 這類「租倉庫」型服務,否則用隨請求走的替代方案,沒有狀態就沒有殭屍。
供應商端的 bug 你永遠防不了。但爆炸半徑,是自己可以畫的。
事件來源
- Google Gemini API 爆「快取計費漏洞」 — 動區 BlockTempo(2026-06-09)
- URGENT: Huge cost cache increase issue (2) — Google AI Developers Forum(2026-06-07)
- URGENT: Huge cost cache increase issue — 三個月前的同類案例(2026-03-18)
- API 金鑰外洩 48 小時慘變噩夢 — T客邦(2026-03-17)
- Dev stunned by $82K Gemini API key bill after theft — The Register(2026-03-03)
- Gemini API key thief racks up $82,314 in charges in just two days — Tom's Hardware(2026-03)