昨天最後留了一個伏筆:護欄服務停機三小時,那三小時發生了什麼?
答案通常是「不知道」。因為在很多系統裡,護欄是這樣接的:
try:
verdict = guardrail.check(prompt)
if verdict.blocked:
return refuse()
except Exception:
pass # 護欄掛了先不管,別擋到業務
return call_llm(prompt)
那行 pass 就是一個 fail-open 決策。它不是誰決定的,它是某天凌晨兩點為了讓 demo 跑起來而寫下的,然後就一直留在那裡。
今天要把這個決策從程式碼裡拉出來,放到架構圖上,並且說清楚誰該為它簽名。
這是資安領域的老問題——防火牆、WAF、DLP 都有同一個抉擇——但 LLM 護欄有兩個新特性讓它更難:
不要試圖為整個系統選一邊。依照攔截點與流量類型分開選,才是可維運的做法。
| 攔截點 | 建議預設 | 理由 |
|---|---|---|
| 使用者輸入 → 內部知識問答 | fail-open + 告警 | 最壞情況是模型講錯話,可用性損失比較貴 |
| 使用者輸入 → 對外客服 | fail-closed(降級回制式回覆) | 對外面子事件的代價高,且可以用固定話術補位 |
| RAG 文件 → 模型 | fail-closed | 間接注入的來源,護欄掛了等於門開著 |
| 工具回傳 → agent | fail-closed | 同上,且下游會動手 |
| 模型輸出 → 工具呼叫參數 | fail-closed,無例外 | 這一條放行的後果是不可逆操作 |
| 模型輸出 → 使用者顯示 | 依場景 | 內部工具可 open,對外或含 PII 場景要 closed |
原則只有一條:下游會「動手」的路徑,一律 fail-closed。
很多人反對 fail-closed 是因為想像成「護欄一掛整個系統就停」。實務上 fail-closed 有階梯:
架構圖上要畫的是這個階梯,不是一個開關。
Model Armor 是託管服務,它掛不掛不是你能控制的,但你能控制的是:
地端護欄是你自己的容器,故障模式你全知道,但也全部要自己處理:
/healthz,閘道層對它做 circuit breaker——連續 N 次失敗就進降級模式,不要每個請求都等 timeout。guardrail_mode=degraded 的標籤進稽核日誌(Day 29),否則事後無法回答「那三小時發生了什麼」。這一題的答案不該是資安部門單方面決定的,因為它本質上是可用性與安全性之間的業務取捨。我在客戶那邊的做法:
聽起來很官僚,但它換來的是:三個月後護欄真的掛了,沒有人需要在凌晨打電話問「現在該怎麼辦」。
為了讓後面 26 天的實驗結果可以比較,本系列統一採用:
Day 5:三層防禦——L1 規則、L2 小模型、L3 LLM-as-judge。為什麼不能只靠一個 guard model?三層各自負責什麼、延遲與成本怎麼分攤、什麼時候該開 L3?
更多 AI 資安筆記:aid3fend.com