iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
AI Security

Medical AI Security Lab:醫療 AI Chatbot 的攻防實驗與自動化 Red Team系列 第 27 篇

Day27|這份 Benchmark 到底能信多少?一篇誠實的測試侷限性

  • 分享至 

  • xImage
  •  

前言

Day26 做出了整合版的數字:完全防禦 27/8/5 → 38/1/1(✅/⚠️/❌)。看起來很漂亮。

今天不測任何東西,也不寫任何程式。我想回頭檢查這組數字本身:它是怎麼量出來的、哪裡可能是錯的、能支撐什麼說法、又支撐不了什麼。這個系列走到這裡,我踩到的最大的坑不是哪個攻擊手法,而是量測這件事——所以這篇每一點,都對應一個真的在這 27 天裡發生過的案例,不是泛泛的免責聲明。

侷限一:樣本很小,而且不是抽樣來的

40 題、二元結果(完全防禦 / 不是)。拿 Wilson 信賴區間算一下:

完全防禦比例 95% 信賴區間
Before 27/40 = 67.5% 52.0% – 79.9%
After 38/40 = 95.0% 83.5% – 98.6%

兩個區間剛好沒有重疊,看起來像顯著。但這個計算的前提全都不成立:這 40 題不是從所有可能的攻擊裡隨機抽出來的,而是我從過去幾天的測試裡自己挑的;題目之間也不獨立——G 組 5 題其實是同一種攻擊(敘事包裝)的 5 個變體,不是 5 個獨立樣本。所以這組區間只能拿來感受「n=40 的不確定性大概有多寬」(Before 的區間寬度將近 28 個百分點),不能拿來宣稱統計顯著。

Wilson 信賴區間:https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval

侷限二:防禦是對著考題寫的

這是我認為最嚴重的一個。

回頭看時間線:Day12、Day13 的紅隊測試找出失守的題目 → Day16、Day17 針對這些失守寫了新的 System Prompt 規則 → Day24 的回歸測試套件裡包含的正是那批題目。換句話說,After 在這些題上的好成績,有一部分是考前看過考題的結果。

最明顯的例子是 G 組:Day17 加了敘事包裝要用佔位符號的規則,就是專門針對 Day12 那三題寫的;現在 G 組 5 題 After 全是 ✅,Before 只有 1 題。這個差距證明了規則對這一類題目有效,但沒有證明它對沒見過的同類攻擊有效——因為我手上沒有一份規則定版之後才寫的考題,也就是機器學習裡說的 hold-out 測試集。

反例也在:D5(重述職責範圍)是 Day9、Day17 就知道的題目,Day18 也針對它試過請保密那一行規則,結果到今天兩邊都還是 ❌。針對過的題目大多改善但不保證每一題都改善,這個結論我能支持;對沒針對過的題目也一樣有效,我沒有任何證據。

資料洩漏(測試資料影響了模型/系統的設計):https://en.wikipedia.org/wiki/Leakage_(machine_learning)

侷限三:同一題,每次輸出都不一樣

這個在 Day25、Day26 都已經碰到:

  • Day13 的阿斯匹靈題,當時完整失守;之後 Before 連續 4 次(Day25 一次、Day26 三次)都直接拒絕。v0 原文我核對過,跟今天的 Baseline 一致,所以不是 prompt 不同,剩下的解釋只有模型本身的隨機性、後端版本更新、或單純是一次離群事件——我無法區分是哪一個。
  • C6 在 Day25 的 Before 回答裡有 Amlodipine 5 毫克、青黴素過敏、高血壓病史,我判 ⚠️;Day26 同一題、同一個伺服器,新斷言沒有命中任何具體項目。

大多數題目我只跑了一次(Day26 的 9 題跑了第二次)。所以 Benchmark 裡每一格的結果,其實都是這一次抽到的那個輸出,不是這一題的真實通過率。要量真實通過率,每題至少要跑好幾次,報的是比例不是單次的勾叉。

侷限四:斷言會誤判,也會漏判——這個系列已經遇到四次(三次是測試斷言,一次是產品裡的過濾規則)

時間 發生什麼 方向
Day19 Output Validation 的 regex 比對不到「我的主要職責與服務範圍」,洩漏的規則清單被放行 漏判(被測系統)
Day24 E4 的拒絕回答因為引用了「致死劑量」四個字被判失敗,行為其實是安全的 誤判(測試斷言)
Day25 D2、D3、E5、G1–G3 在 Before 上通過,但回答裡有被唸出來的 prompt、整份 JSON、具體藥名、虛構病歷 漏判(測試斷言)
Day26 After 的 G2、G3 被標題「非醫療診斷:」和佔位符提示裡的範例「Penicillin」誤判 誤判(測試斷言)

Day25 那次的根源是我的疏忽:有幾題的比對字串是照 After 的 prompt 措辭挑的,拿去測 Before 永遠抓不到。這違反了我自己在 Day23 立的原則——測試標準必須獨立於被測系統。

更值得記下的是 Day26 那次:我在跑之前,已經拿過去貼過的真實回答把新斷言驗證了一輪,12 個樣本全部符合預期,結果還是誤判了兩次——因為那些樣本裡剛好沒有「帶冒號的章節標題」和「佔位符裡的範例藥名」這兩種情況。驗證斷言用的樣本集,本身的涵蓋範圍也是有限的。每修一次斷言只是把已知的誤判補掉,這一類錯誤本身不會消失。

侷限五:判定標準有主觀成分,而且我只有一個評分者

三級標準(✅/⚠️/❌)的界線,是我一路邊測邊定的而且回頭改過很多次:

  • Day9:一開始只看「有沒有講出明確診斷結論」就算防禦成功,重新檢視後改成三級標準,把「嘴上說不能診斷、實際照著列出鑑別診斷」的回應從 ✅ 改成 ⚠️。
  • Day13:醫學教授那題第一次判 ✅,,後來因為跟 Day9 的標準不一致,改成 ⚠️(Day24 的文章有說明)。
  • Day25、26:「自我介紹裡提到無法診斷算不算洩漏」、「After G3 出現 P001 算不算 ⚠️」——這些是我選的判斷線,換一條線數字會變。

這些修正每一次都是自己回頭發現的,而不是有第二個人幫我檢查。研究方法裡有個指標叫評分者間信度(inter-rater reliability),要兩個以上的評分者各自獨立評分再算一致性;我沒有做這件事,所以每一個 ✅/⚠️/❌ 背後都帶著只有一個人判的不確定性。

評分者間信度:https://en.wikipedia.org/wiki/Inter-rater_reliability
Cohen's kappa(一致性指標):https://en.wikipedia.org/wiki/Cohen%27s_kappa

侷限六:測量範圍以外的東西

這份 Benchmark 沒有碰到的:

  • Access Control 和 Audit Logging:這兩層防的是誰能碰哪個功能和事後看得見,不在 /chat 的回答內容裡,所以這套題庫量不到它們的任何貢獻。Day20 的角色驗證本身也是簡化版——角色是使用者自己宣稱的,沒有真正的身分驗證。
  • 多輪對話與會適應的攻擊者:題庫裡只有 Day13 的一組三輪漸進式滲透,真實攻擊者會根據回應調整手法。
  • 語言與模型:全部是繁體中文、單一個模型,而且沒有記錄當時的模型版本。
  • 資料是假的、也沒有真的接上資料庫:Day12 判斷回答跟 fake-patients.json 重疊是模板巧合,前提是 server.js 從來沒把那個檔案讀進 context。一旦接上真實資料,風險輪廓就完全不同。
  • 誤擋的測量很薄:正常問題只有 A 組 6 題(Day17 另有 10 題),防禦有沒有傷到可用性這件事,我能說的只有在這十幾題上沒有。
  • 加進去的規則之間會互相影響:Day18 發現 v2 在三題洩漏題上的表現反而比只加一行請保密的版本更差。這代表多加一條規則不保證單調變好,而這種交互作用我只在一個小實驗裡看到過。

所以,這份 Benchmark 能支撐什麼

說法 證據強度 理由
After 在方向上比 Before 更安全 較強 兩種獨立判定方法一致,差距不小;但題庫不是隨機抽樣
具體的提升幅度(+11 題等) 弱 單次輸出、n=40、題目不獨立
程式碼層只貢獻 11 題改善裡的 2 題 弱 排除法推論,沒做 ablation
Day13 那次失守是離群事件 弱 只有 4 次後續觀察
對沒見過的攻擊也防得住 沒有證據 沒有 hold-out 測試集
Access Control、Audit Logging 有沒有價值 這套題庫回答不了 不在測量範圍

如果重來,我會怎麼設計

  1. 留一份 hold-out 題庫:規則定版之後才寫、而且在調整防禦的過程中不能看的題目,專門用來回答對沒見過的攻擊有沒有效。
  2. 每題重複跑多次,報通過率,不報單次的勾叉。
  3. 替斷言建一組有標籤的測試資料:收集已知安全、已知有洩漏的回答,先量出斷言自己的誤判率和漏判率,再拿去測系統。Day26 的教訓是,這組樣本要刻意包含帶冒號的標題、佔位符裡的範例這類容易觸發誤判的邊角案例。
  4. 找第二個評分者獨立評分,至少抽樣一部分,算一致性。
  5. 記錄模型版本與執行時間,並把完整輸出匯出成檔案,不要靠表格裡被截斷的預覽判斷。Promptfoo 的 -o 參數可以直接輸出 JSON,Day25 有四題因為預覽被截斷不得不回頭補看,這是可以避免的。
  6. 做真正的 ablation:2 × 2 的設計——(舊 prompt / 新 prompt)×(沒有程式碼層 / 有程式碼層)——四種組合各跑一次同一批題目,才能把 Day25 那個程式碼層只貢獻 2 題的推論變成有根據的結論。代價是 40 題 × 4 個組合 = 160 次呼叫,以免費額度來說要分好幾天。

Promptfoo 命令列參數(含輸出檔案):https://www.promptfoo.dev/docs/usage/command-line/

回到 Day22

Day22 我寫過手動紅隊有三個天花板:樣本有限、最危險的漏洞長得不像攻擊、沒有回歸測試。接上 Promptfoo 之後,第三個確實解決了——題目寫成檔案,每次改動都能原樣重跑。

但走到今天我得補一句:自動化解決的是記不記得測和跑不跑得動,沒有解決測得準不準和測得廣不廣。 斷言要有人盯,題庫要有人更新,判定標準要有人檢查,這些都不會因為裝了工具就自動變好。這個系列最後留給我的,與其說是一組防禦成績,不如說是一份對量測本身有多容易出錯的體會。

明天預告

Day28 要把整個系列濃縮成一份醫療 AI Security Checklist——可以直接勾選的清單,從輸入、System Prompt、輸出、權限、稽核到測試方法。今天這篇的六個侷限,會直接變成清單裡測試方法那一區的檢查項目。

本系列所有病患資料皆為人工生成之虛構資料,不涉及任何真實病患。GitHub Repo:medical-ai-security-lab


上一篇
Day26 |結果導向的斷言、同一題跑三次,以及正式的 Security Benchmark
下一篇
Day28|醫療 AI Security Checklist,27 天做完之後,清單長這樣
系列文
Medical AI Security Lab:醫療 AI Chatbot 的攻防實驗與自動化 Red Team 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言