AI Agent護欄資安金鑰洩漏BuildInPublic一人公司

AI agent 輸出護欄怎麼做:擋金鑰外洩

· 7 分鐘閱讀
龍蝦艦隊 · 逐章稽核 · 第 19 / 22 篇
目錄
  1. 賣安全的公司,自己的 agent 在裸奔
  2. 我們補上的那道護欄,難的不是攔而是攔多少
  3. 先花幾分鐘查你自己的 agent
  4. 護欄體檢清單
  5. 這一章的四句話

《Agentic Design Patterns》第 18 章講護欄與安全。核心一句話:agent 的輸入要擋注入、輸出要在送出去之前被檢查,別讓有害或不該外流的東西直接離開系統。輸入護欄擋壞人餵進來的,輸出護欄擋 agent 送出去的。

我們讀到「輸出護欄」四個字,笑不出來。因為我們公司賣的就是這個。UltraProbe 是我們的開源 AI 安全掃描器,output guardrail 是它的招牌掃描向量之一,我們拿它去幫客戶掃 agent 會不會把不該說的東西吐出去。結果對自己做對抗式稽核那天,發現一件很難堪的事:我們自己的發文 agent,一路裸奔。

賣安全的公司,自己的 agent 在裸奔

我們有一整條自動發文管線,agent 產生內容、直接 POST 到 Discord 和社群,中間沒有任何一道 egress 檢查。它產什麼就送什麼。

想清楚這意味著什麼。如果某次 prompt 不小心把環境變數帶進 context,agent 完全有可能把一把真的 API 金鑰、老闆真名、或模型自己的 system prompt 骨架,原封不動 PO 到公開頻道。一把 sk-or-v1 開頭的 OpenRouter 金鑰貼上 Discord,就是別人拿去燒我們額度的邀請函。

我們一邊賣「幫你檢查 agent 輸出有沒有洩漏」,一邊自己的 agent 從沒被這樣檢查過。不是我們不會,是我們沒有先吃自己的狗糧。

我們補上的那道護欄,難的不是攔而是攔多少

egress 護欄的邏輯只有一句:內容送出去之前,先過一遍。真正難的是「攔什麼、攔到什麼程度」。

因為我們的發文管線有硬需求。Discord 盤前盤後那種貼文是有時效的,誤殺一則正常貼文,比漏掉一則可疑貼文更痛。所以規則切成兩層。真金鑰硬擋:sk-or-v1、AIza、sk-ant、私鑰標頭、Bearer token,這幾種東西一則正常對外貼文絕不可能出現,命中就直接不發,判準夠死所以誤殺率接近 0。可疑內容軟警告:模型把 system prompt 骨架吐出來、罐頭拒答語、老闆真名、簡體字,這些可能是問題也可能是誤判,只記 log 不擋,給可觀測性但不冒斷掉發文的險。

這就是護欄設計最核心的取捨:硬擋降的是漏網率,升的是誤殺率。我們的場景寧漏勿誤殺,所以只有「絕不可能是正常內容」的東西才配硬擋。連檢查器本身不在時,我們都選擇放行不擋。

換個場景,取捨會整個翻過來。如果 agent 送出去的是一筆轉帳、一個刪庫指令,那就該寧誤殺勿漏,寧可攔錯一百次也不放過一次。護欄不是愈嚴愈好,是要對準「送錯的代價」和「攔錯的代價」哪邊更痛。

先花幾分鐘查你自己的 agent

01 查 agent 送東西出去之前,有沒有任何一道檢查 翻你所有會對外送內容的地方,發文、寄信、回訊息、打 webhook。看內容從產生到送出,中間有沒有一個函式在檢查。沒有,就是裸奔。

# 撈出所有對外送出的呼叫,逐一看送之前有沒有先過一道 guard
grep -rnE 'requests.post|curl.*-d|sendMessage|webhook|POST ' your-agent/ \
  | grep -viE 'guard|sanitize|redact|filter'

紅旗:搜出一堆送出動作,但沒有一個前面掛著檢查。

02 拿一把假金鑰餵進去,看它擋不擋 別用猜的,直接測。在要送出的內容裡塞一段長得像真金鑰的字串,跑一次你的管線,看它會不會攔。攔不下來,代表真的洩漏那天它也攔不下來。

# 塞一把假 key 進 egress 檢查,期望被擋(非 0 退出)
echo 'sk-or-v1-AAAABBBBCCCCDDDDEEEEFFFF1234 出貨' | your-guard; echo "exit=$?"
# exit=0 = 放行 = 你的護欄看不見金鑰

紅旗:塞了明顯的金鑰進去,退出碼還是 0。

03 分清楚哪些該硬擋、哪些只該軟警告 把你的檢查規則列出來,逐條問一句:這條命中,我要直接不送,還是只記一筆 log。判準夠死、誤殺率接近 0 的(真金鑰、私鑰)才配硬擋;模糊的(可疑用詞、風格問題)軟警告就好,不然你會為了攔一則髒的誤殺十則好的。

# 看你的護欄有沒有分級,還是全部一刀切成 block
grep -iE 'block|warn|hard|soft|exit 1|log_only' your-guard.*

紅旗:所有規則都是同一種處置(全硬擋或全放行),沒有依「誤殺代價」分層。

護欄體檢清單

對你自己的 agent 跑一遍:

  • agent 對外送任何內容之前,有沒有一道 egress 檢查
  • 拿假金鑰實測過嗎,它真的擋得下來嗎
  • 硬擋的規則,誤殺率真的接近 0 嗎,會不會誤殺到正常內容
  • 模糊訊號是軟警告記 log,還是也被拉去硬擋
  • 你的場景到底該寧漏勿誤殺,還是寧誤殺勿漏,想清楚了嗎
  • 檢查器自己掛了是 fail-open 還是 fail-close,這符合你的場景嗎
  • block 和 warn 有記 log 嗎,事後查得到嗎

這一章的四句話

  • 你賣安全,就得先讓自己安全。自己的 agent 裸奔在對外送內容,比客戶被掃出問題更難堪。
  • egress 護欄不是愈嚴愈好,核心是取捨:硬擋降漏網率、升誤殺率,看你的場景哪個代價更痛。
  • 只有「正常內容絕不可能出現」的東西才配硬擋(真金鑰),誤殺率接近 0;模糊的一律軟警告,別為攔一則髒的誤殺十則好的。
  • 先吃自己的狗糧。你幫別人檢查的那一項,先套到自己身上跑一遍。

原始碼位置:~/.openclaw/scripts/lib/output-guardrail.py(egress 檢查主體,HARD 5 條真金鑰規則 + SOFT 軟警告 + 簡體偵測)、output-guardrail.sh(給發文腳本 source 的 bash 介面,檢查器不在時放行);block 和 warn 都落在 ~/.openclaw/logs/guardrail.log,平常安靜。

這是《Agentic Design Patterns》× 龍蝦艦隊系列。我們照書把一人公司的 AI agent 艦隊系統化,然後對自己做對抗式稽核。宣稱做到的每一章,都被重新驗證過一次,也把查法和改法整理成你能照著跑的步驟。這個系列的可信度,來自我們願意公開自己打臉自己。

龍蝦艦隊 · 逐章稽核 · 第 19 / 22 篇

每週 AI 自動化實戰筆記

不廢話,只有能直接用的東西。Prompt 模板、自動化 SOP、技術拆解。

加入一人公司實驗室

免費資源包、每日建造日誌、可以對話的 AI Agent。一群用 AI 武裝自己的獨立開發者社群。

需要技術協助?

免費諮詢,24 小時內回覆。