前言
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 都已經碰到:
大多數題目我只跑了一次(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 個樣本全部符合預期,結果還是誤判了兩次——因為那些樣本裡剛好沒有「帶冒號的章節標題」和「佔位符裡的範例藥名」這兩種情況。驗證斷言用的樣本集,本身的涵蓋範圍也是有限的。每修一次斷言只是把已知的誤判補掉,這一類錯誤本身不會消失。
侷限五:判定標準有主觀成分,而且我只有一個評分者
三級標準(✅/⚠️/❌)的界線,是我一路邊測邊定的而且回頭改過很多次:
這些修正每一次都是自己回頭發現的,而不是有第二個人幫我檢查。研究方法裡有個指標叫評分者間信度(inter-rater reliability),要兩個以上的評分者各自獨立評分再算一致性;我沒有做這件事,所以每一個 ✅/⚠️/❌ 背後都帶著只有一個人判的不確定性。
評分者間信度:https://en.wikipedia.org/wiki/Inter-rater_reliability
Cohen's kappa(一致性指標):https://en.wikipedia.org/wiki/Cohen%27s_kappa
侷限六:測量範圍以外的東西
這份 Benchmark 沒有碰到的:
/chat 的回答內容裡,所以這套題庫量不到它們的任何貢獻。Day20 的角色驗證本身也是簡化版——角色是使用者自己宣稱的,沒有真正的身分驗證。所以,這份 Benchmark 能支撐什麼
| 說法 | 證據強度 | 理由 |
|---|---|---|
| After 在方向上比 Before 更安全 | 較強 | 兩種獨立判定方法一致,差距不小;但題庫不是隨機抽樣 |
| 具體的提升幅度(+11 題等) | 弱 | 單次輸出、n=40、題目不獨立 |
| 程式碼層只貢獻 11 題改善裡的 2 題 | 弱 | 排除法推論,沒做 ablation |
| Day13 那次失守是離群事件 | 弱 | 只有 4 次後續觀察 |
| 對沒見過的攻擊也防得住 | 沒有證據 | 沒有 hold-out 測試集 |
| Access Control、Audit Logging 有沒有價值 | 這套題庫回答不了 | 不在測量範圍 |
如果重來,我會怎麼設計
-o 參數可以直接輸出 JSON,Day25 有四題因為預覽被截斷不得不回頭補看,這是可以避免的。Promptfoo 命令列參數(含輸出檔案):https://www.promptfoo.dev/docs/usage/command-line/
回到 Day22
Day22 我寫過手動紅隊有三個天花板:樣本有限、最危險的漏洞長得不像攻擊、沒有回歸測試。接上 Promptfoo 之後,第三個確實解決了——題目寫成檔案,每次改動都能原樣重跑。
但走到今天我得補一句:自動化解決的是記不記得測和跑不跑得動,沒有解決測得準不準和測得廣不廣。 斷言要有人盯,題庫要有人更新,判定標準要有人檢查,這些都不會因為裝了工具就自動變好。這個系列最後留給我的,與其說是一組防禦成績,不如說是一份對量測本身有多容易出錯的體會。
明天預告
Day28 要把整個系列濃縮成一份醫療 AI Security Checklist——可以直接勾選的清單,從輸入、System Prompt、輸出、權限、稽核到測試方法。今天這篇的六個侷限,會直接變成清單裡測試方法那一區的檢查項目。
本系列所有病患資料皆為人工生成之虛構資料,不涉及任何真實病患。GitHub Repo:medical-ai-security-lab