資安指南

API key 從 AI 寫的程式碼外洩並被盜刷:原因是未修補的 CVSS 10.0 漏洞

個人開發者真的會遇到的模式:借助 AI 上線的應用程式,API key 被偷走,跑出一堆陌生的批次任務把帳單刷爆。原因一開始如何被誤判、實際原因(公開已久卻數月未修補的 CVSS 10.0 RCE)如何被找出,以及如何防止復發。不含攻擊步驟。

發布於 2026-06-07 更新於 2026-10-06 閱讀時間 5 分鐘
本頁內容

本文把沒有資安背景的個人開發者常遇到的事故,隱去所有可識別的細節後整理成教訓。文中沒有重現攻擊的步驟。目的是防禦,讓同樣的錯誤不會發生在你身上。

事故概要 — INCIDENT FILE
類型
API key 洩漏 / 盜刷
嚴重度
Critical(被利用的是公開的 CVSS 10.0)
根本原因
Web 框架的認證前 RCE 數月未修補
洩漏範圍
環境中的所有 secret
執行範圍
侷限在非特權容器內(主機 root 未受害)
根治措施
①升級到修補版 ②輪換所有 key ③以機器監控 CVE
10.0
CVSS / 最嚴重等級
數月
未修補的時間
整個 env
假設的洩漏範圍
監控
最有效的預防

「止住了帳單」≠「處理完成」

止住帳單只是暫時措施。封堵洩漏途徑是另一項工作。兩件都做完,才算處理完成。

發生了什麼(時間軸)

  1. Day 0 — 上線並運作

    借助 AI 寫好的應用程式上線,在正式環境中運作。
  2. 某一天 — 帳單暴漲

    雲端 AI 的帳單突然飆升。跑的是絕不會用到的模型,做的是不屬於自己的大量處理。
  3. 調查 — 第三方濫用

    「自己的應用程式失控」解釋不了。是第三方拿著偷來的 key 在跑。
  4. 追查 — 調查洩漏途徑

    「那麼 key 是從哪裡漏出去的?」真正的調查從這裡開始。

為什麼一開始沒有發現

依照犯錯的順序寫下來,因為這些錯誤本身就是教訓。

1

太早認定原因

最初的假設是「自己的備援程式碼出錯了」。但資料(實際處理的內容)清楚顯示不可能是那樣。
→ 在認定「是我的錯」或「是別人的錯」之前,先看資料。
2

grep 乾淨,差點就結束調查

搜尋了全部程式碼、git 歷史、關聯的儲存庫 → 哪裡都沒有明文 key。差點以「無從追查」收手。只看檔案,就漏掉了執行階段的洩漏。
3

掩蓋症狀感覺像修好了

在代理層掩蓋症狀,差點就覺得處理完了。但掩蓋之後 RCE 仍然存在。在原因修正之前,它一直可以被利用。

grep 乾淨不代表沒事

即使任何檔案裡都沒有 key,漏洞也可能從正在執行的程序中取出環境變數。洩漏會發生在執行階段(RCE、HTTP 標頭),不只在檔案裡。詳見 什麼是 RCE。

實際原因:一個公開卻未修補的 CVSS 10.0

舊存取記錄中一個奇怪的特徵,很快就和威脅情報對上了。所使用的 Web 框架版本範圍,存在一個 公開的認證前 RCE(CVSS 10.0),而且已經在實際環境中被利用。它卻在未修補的狀態下運作了好幾個月。

  • 這不是被動的 bug,而是攻擊者 在伺服器上執行程式碼並把環境帶走。
  • 有一點限制了損害:執行 侷限在非特權容器內(主機 root 沒有被拿走)。入侵調查沒有發現常駐後門、挖礦程式或 C2,確認的影響是 secret 被竊。
  • 由於內部 DB 可以連到,因此應對時假設 DB 內容也已外洩。
看得見的症狀:意外、陌生的帳單
擁有者只看得到這裡
↑ 被偷的 key 之後被轉賣/濫用
整個 env(所有 secret)被帶走
↑ 攻擊者在正式伺服器上執行任意程式碼
原因:公開卻未修補的 CVSS 10.0(pre-auth RCE)
意外的帳單只是看得見的症狀。底下的原因是一個公開卻未修補的 CVSS 10.0。

教訓:行為異常時,先懷疑已知的 CVE。不要假設是自己的 bug。

縮小洩漏範圍:那個 key 存放在哪裡?

grep 找不到時,就換個搜尋方式。列出被濫用的 key 曾寫在哪些地方,可能的洩漏途徑就會縮小。例如被濫用的 key 只存在於正式伺服器的環境變數中,就該懷疑正式伺服器或主機業者,而不是 Git 或瀏覽器。

洩漏位置常見原因如何檢查自己的環境如何封堵
Git 歷史/公開儲存庫提交了 .env、把 key 寫死在程式碼中用 gitleaks git 掃描完整歷史。查看 GitHub secret scanning 的警示先撤銷,再在提交前攔截
送到瀏覽器的 JavaScript把 key 放在 NEXT_PUBLIC_ 變數中、直接從瀏覽器呼叫 API在建置輸出中搜尋 key 的前綴把 API 呼叫移到伺服器端程式碼
公開的網站資料夾.env 或備份放在公開資料夾中在自己的網站開啟 /.env,確認回傳 404 或 403把機密檔案移到公開資料夾之外
記錄/錯誤頁面開著除錯輸出上線、把請求標頭原樣寫入記錄檢查正式環境的除錯設定,以及記錄中是否出現 Authorization 等關閉除錯輸出,並在記錄中遮蔽機密
正在執行的伺服器公開的漏洞(例如 RCE)未修補比對實際執行的版本與公告中的修補版本升級,然後更換環境中的所有 secret
主機業者業者端被入侵查看業者的安全公告與電子郵件通知以存檔後無法再檢視值的方式存放機密,並輪換
你的開發電腦惡意套件或擴充功能檢查安裝的套件或擴充功能版本是否符合已公開的入侵事件移除該版本,並更換那台電腦上的 secret

這次的案例屬於「正在執行的伺服器」那一列。最下面四列是不會在程式碼或 Git 中留下痕跡的途徑。OWASP 的 Secrets Management Cheat Sheet 也提醒,環境變數常常能被同一環境中的其他程序讀取,也可能被寫進記錄或傾印檔中。所以只要有一個 key 被濫用,就要把存放在同一處的所有 secret 視為已外洩。

分開使用 key,調查會更快

如果每個服務、每個環境(正式與開發)都使用不同的 key,光看被濫用的 key 就知道是表中的哪一列。到處共用同一個 key,就必須懷疑所有位置。如何拆分 key,請見 API key 被盜導致 OpenAI 帳號被停權時。

依實際執行的版本計算漏洞

檢查其他相依套件時,回報說「另外還有 8 個有漏洞的相依套件」。這也錯了。它們是依 package.json 中的 下限(^ caret 範圍)計算的。真正危險的,只有被固定版本而落後的 2 個相依套件。

確認自己實際執行的版本

查看 lock 檔案或正在執行的容器中實際解析出的版本。

# npm: see what's actually installed
npm ls next react react-dom
 
# inside a running container
docker exec <container> npm ls <package>

這裡顯示的數字才是實際執行的版本,而不是 package.json 裡的 ^。

如何檢查自己的環境

無論你是剛注意到奇怪的帳單,還是什麼事都還沒發生,都可以依以下順序檢查。每一步都只是查看自己的帳戶和伺服器。

1

查看用了哪個 key、什麼時候用的

在 AI API 的管理介面中,按專案(Anthropic 是 Workspace)和日期拆分用量與費用。出現在你從不使用的模型上、或在你的程式都沒在跑的時段出現的用量,代表那個 key 已外洩。接著從上表中那個 key 存放位置的那一列開始查。
2

檢查送到瀏覽器的檔案

在 Next.js 中,以 NEXT_PUBLIC_ 開頭的環境變數值,會在建置時被嵌入送往瀏覽器的 JavaScript。建置後,在輸出中搜尋 key 的前綴,例如 grep -rl "sk-" .next/static。在那裡找到的東西,任何人都讀得到。
3

確認機密檔案無法從公開資料夾存取

對自己的網站執行 curl -sI https://example.com/.env(把 example.com 換成你的網域),確認第一行的狀態碼不是 200(應該是 404 或 403)。更多內容請見 檢查公開目錄中的機密檔案。
4

比對正式環境版本與公告

如上方方框所示,在正式環境的容器內執行 npm ls 查看版本。osv-scanner scan -L pnpm-lock.yaml 會檢查你的 lock 檔案是否包含有已知漏洞的版本。
5

檢查記錄中是否有機密

對存放應用程式記錄的資料夾執行 gitleaks dir --redact,找出寫進記錄的 key。--redact 會讓找到的值本身不顯示在畫面上。
6

檢查上限與警示

OpenAI 可以在管理介面的 limits 頁面設定支出警示和每月硬性支出上限。Anthropic 可以為每個 Workspace 設定支出上限。請確認你不是只有不會擋下任何東西的警示。

最初做了什麼(可重現的步驟)

1

立即撤銷被濫用的 key

止住損害,但這只是工作的一部分。
2

把框架升級到修補版

真正封堵 RCE。升級後,在記錄中確認洩漏的特徵已消失。
3

輪換所有 secret

假設已外洩。依「在任何地方都能被濫用的優先」排序:物件儲存的 key → 工作階段簽章 key → API key → DB 憑證。
4

入侵調查

檢查是否有常駐程式、異常的 cron、對外的 C2 通訊(這次都沒有)。
5

帳戶端的防禦

更改密碼、啟用 MFA,確認有沒有陌生的 API key。

預防:自動監控 CVE

歸根結底,這次事故就是「人漏看了一個公開的 CVSS 10.0」。人工檢查一定會漏,自動監控就能抓到。

今天就能開始的相依套件掃描

免費就能開始,只要在 CI 裡加一個步驟。

# OSV scanner (Google) checks your lockfile
osv-scanner scan -L pnpm-lock.yaml
 
# On GitHub, enable Dependabot (repo Settings → Security)

本站自己也依照這個教訓,監控自身相依套件的 CVE,我們自己也在做我們建議的事。

常見錯誤與修正方式

  • 在仍有漏洞的伺服器上放新的 key:同一個途徑也會把新 key 偷走。立刻停用被濫用的 key,修正漏洞,然後再完成其餘 secret 的更換。
  • 把預算警示當成上限:Google Cloud 說明只有警示的預算不會自動停止用量或支出。如果要讓它停下來,請加上會擋下用量的上限,例如 OpenAI 的每月硬性上限或 Anthropic 的 Workspace 支出上限。
  • 把 AI API key 放進瀏覽器或行動 App:任何送到使用者裝置上的值都能被取出。請從你的伺服器呼叫 AI API,再讓瀏覽器呼叫你的伺服器。
  • 從檔案或 Git 歷史中刪除就停手:已經複製走的人仍然可以使用。先撤銷,之後再清理歷史(見 為什麼 GitHub 上外洩的憑證仍然有效,英文)。
  • 開發和正式環境使用同一個 key:無法分辨是哪一邊外洩,只好兩邊都停。請為每個環境核發不同的 key。

公開案例:環境變數從服務提供者那一側外洩

任何檔案搜尋都找不到的洩漏,也會發生在你自己的伺服器之外。2026 年 4 月 19 日,Vercel 公布其內部系統遭到未經授權存取。根據該公司的說明,一名員工使用的第三方 AI 工具遭入侵,導致部分客戶未標記為「sensitive」(儲存後無法再檢視值的設定)的環境變數被竊。

Vercel 建議客戶檢查並輪換未標記為 sensitive 的環境變數,並檢查活動記錄和近期的部署。該公司也表示,刪除專案或帳號並不足以消除風險。

處於這種情況的客戶,就算整天搜尋自己的程式碼和 Git,也找不到任何洩漏的痕跡。該採取的行動與本案例相同:更換存放在那個地方的所有 secret。步驟請見 Vercel 資安事件(2026 年 4 月)(英文)。

教訓

常見的錯誤

  • 以「止住了帳單」就當作處理完成
  • grep 乾淨就放心
  • 在代理層掩蓋症狀,就覺得修好了
  • 依 package.json 的下限計算漏洞
  • 只輪換確認被濫用的那一個 key

正確的防禦

  • 把止住盜刷和封堵洩漏途徑當作兩件事,兩件都做
  • 也懷疑執行階段的洩漏(RCE、標頭)
  • 更新造成問題的框架
  • 依實際執行的版本判斷
  • 一旦外洩就更換整個 env

總結:帳單暴漲是症狀,原因是一直沒修補的 CVSS 10.0 RCE。正確的原因不是第一次就找到的,而是在多次出錯並重新檢查後才找到的。

接下來閱讀

參考資料

  • OWASP, "Secrets Management Cheat Sheet"(環境變數的風險、外洩時的應對):cheatsheetseries.owasp.org
  • Next.js Docs, "How to use environment variables in Next.js"(NEXT_PUBLIC_ 的嵌入):nextjs.org
  • OSV-Scanner, "Usage":google.github.io
  • OpenAI, "Production best practices"(key 的處理、警示與上限):developers.openai.com
  • Claude Help Center, "Creating and managing Workspaces"(Workspace 的上限與 key):support.claude.com
  • Google Cloud, "Create, edit, or delete budgets and budget alerts":docs.cloud.google.com
  • Vercel, "Vercel April 2026 security incident":vercel.com

FAQ

QAPI key 洩漏了,只撤銷被濫用的那一個就夠了嗎?
A

不夠。如果洩漏途徑是在執行階段(RCE 或請求標頭洩漏),就要假設環境中的所有 secret 已經一次全部外洩,並全部輪換。你看到被濫用的 key,只是外洩內容的一小部分。

Q把程式碼和 git 都 grep 過,沒找到 key 就安全了嗎?
A

不一定。即使任何檔案裡都沒有 key,框架的漏洞也可能直接從正在執行的程序中把環境變數抽走。洩漏不只發生在檔案裡,也會發生在執行階段。

Q最可靠的復發防範是什麼?
A

用機器監控相依套件的 CVE。這次的原因是一個公開的 CVSS 10.0 被人為疏忽了好幾個月,Dependabot 或 osv-scanner 可以自動抓出這種問題。

QAI API 的帳單突然暴增,第一步該做什麼?
A

先在服務提供者的管理介面停用被濫用的 key,止住損害。接著從那個 key 的存放位置縮小洩漏途徑,修正漏洞或設定錯誤,之後再更換存放在同一處的所有 secret。只撤銷 key,洩漏途徑仍然開著。

Q怎麼知道是哪個 key 洩漏了?
A

在 AI API 的管理介面中,按專案(Anthropic 是 Workspace)拆分用量和費用。出現在你從不使用的模型或時段上的用量,背後的 key 就是外洩的那一個。如果你為每個服務和環境使用不同的 key,那個 key 的存放位置也就指出了洩漏途徑。

Q設定了預算警示,就能阻止盜刷嗎?
A

不一定。以 Google Cloud 為例,官方說明只有警示的預算不會自動限制用量或支出。要真正停止使用,請設定會擋下用量的上限,例如 OpenAI 的每月硬性支出上限,或 Anthropic 的每個 Workspace 支出上限。