iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0

全貌

使用者請求
   │
   ├─ 從請求文字抽出授權範圍(email、IBAN、動作詞)───┐
   │                                            │
規劃器產生程式碼                                   │
   │                                            │
   ↓                                            │
CaMeL直譯器逐個呼叫執行                            │
   │                                            │
   ├─ 每個呼叫 → 動態權限層 ───────────────────────┤
   │      ↓                                     │
   │   ①偵測繞道 → ②看威脅等級 → ③依等級選授權來源 ←┘
   │      ↓
   │   放行 or 拒絕
   │      ↓
   └─ 被拒絕 → 累積訊號 → 有界重擬 or 放棄

三層分別各做一件事,累積訊號、依等級決定授權來源、被擋之後有界地再試。

第一層:訊號

CaMeL執行過程中會產生一些資訊,但原本用完就丟,這一層把它們留下來,三種訊號,分數到2是可疑,到4是已被操縱,各有權重:

訊號 權重 什麼時候記
政策拒絕 2 某個呼叫被擋下來
隔離區拒絕回答 3 隔離模型判斷內容可疑而不回答
參數帶不可信資料 0 呼叫的參數來自工具輸出

第二層:權限格

等級決定什麼東西可以替一個呼叫背書:

等級 可用的授權來源
乾淨 使用者授權範圍 可讀者檢查
可疑 只剩可讀者檢查
已被操縱 全部拒絕,會改變狀態的呼叫一律停用

乾淨層比靜態政策寬,這是整個設計的關鍵。

乾淨層必須能放行靜態政策擋掉的東西,授權來源就是使用者自己在請求裡指名的目的地,要把檔案寄給某個地址,那個地址就是被授權的,就算可讀者檢查答不出來也算,這個「寬」有嚴格邊界,只有is_trusted那一類的拒絕可以被翻掉。直譯器自己的資訊流檢查不能翻。

第三層:有界重擬

被拒絕之後不直接失敗,給重新規劃的機會,但有三道界線:

界線 預設 防什麼
總重擬次數 3 無限重試
單一工具拒絕上限 2 在同一個工具上反覆試參數
繞道偵測 換個寫法瞄準同一個被擋過的目的地

Progent被擋之後給模型的訊息是「試試其他工具或參數繼續完成任務」,等於把政策引擎變成一個可以無限查詢的預言機——攻擊者靠反覆試探就能摸出邊界在哪。有界就是不讓它問到底,把隔離區的拒絕當成一般錯誤丟回去除錯,模型會被告知「換個參數再試一次」,然後把額度全部燒在同一個問題上。

每次執行的結果分五類,沒觸發、被救回、預算耗盡、繞道被擋、隔離區拒絕後停止。只看utility分不出「任務成功是因為機制有效」還是「根本沒觸發」。

四個洞,同一條判斷線

Day22到Day25每天研究一個,當時看起來是四件事,收斂成同一件事:

問題出在
22 字面值冒充使用者授權 is_trusted分不出使用者打的字與模型寫的常數
23 授權範圍蓋過資訊流檢查 使用者指名一個目的地,不代表授權把整個硬碟送過去
24 可讀者檢查形同虛設 所有欄位都是公開常數時,迴圈跑完沒觸發拒絕就算通過
25 修完第24天反而擋掉合法目的地 沒有敏感資料可背書,不等於這個呼叫可疑
  • 常數:規劃器一行程式碼就寫得出來,攻擊者控制得到。需要外部背書——要嘛在使用者授權範圍內,要嘛有真正受限的資料的可讀者涵蓋它。
  • 非常數:真的來自某次工具呼叫,帶著自己的依賴追蹤,攻擊者偽造不出來。交給原本的政策引擎判斷就好。

Day22抓的是常數被錯誤放行,Day25抓的是非常數被錯誤擋下,同一條線的兩端。

三條不變式

一、收權限只能減不能加。 原本政策拒絕的,這一層不放行,除非拒絕理由屬於is_trusted那一類可翻的。

二、使用者授權不能蓋過資訊流檢查。 使用者指名的目的地能翻掉身分判斷,不能翻掉直譯器對資料依賴的判斷。

三、只觀測模式的行為要跟原版完全相同。 掛上這一層但不改任何判斷,結果應該一模一樣,這條可以用來確認這層本身沒有副作用。

程式結構

檔案 行數 職責
threat_state.py 199 訊號累積、等級判定、執行結果分類
adaptive_policy.py 311 包在原本政策引擎外面,依等級決定授權來源

改動的是規劃器那一端(有界重擬、兩條拒絕路徑)與命令列參數。

測試193個,分五層:

檔案 測試函式 守什麼
test_adaptive_policy.py 32 權限格的每條分支與四個洞的回歸
test_bypass_and_outcomes.py 11 繞道偵測與結果分類
test_security_replan.py 8 重擬預算與界線
test_threat_state.py 8 訊號累積與等級判定
test_count_tokens.py 6 既有功能不受影響

訊號記錄與政策判斷必須拆開,原本在政策檢查之後才記訊號,導致政策看不到當下這個呼叫的污染狀況。拆成「檢查前記錄參數污染」與「檢查後記錄拒絕」兩步。

這套設計做不到的事

看不見的風險類型。訊號全部來自能力標籤與政策拒絕,都是確定性的,好處是不會誤判,代價是視野窄,參數值是不是模型幻想出來的、工具描述跟名稱符不符,能力標籤回答不了。

閾值是設出來的,不是學出來的。2跟4這兩個門檻來自觀察,沒有經過校準。

狀態可以被惡意推升。等級會升代表攻擊者可以想辦法把它推上去,推到已被操縱之後使用者的正常工作就被擋了。這是這個設計自己造出來的攻擊面,成本多少沒有量過。

適用面窄。昨天的數字是40個workspace任務裡5個觸發、16個banking任務裡7個,符合「需要判斷目的地」這個形狀的任務本來就不多。

小結

這套機制的核心只有一句話:權限應該是執行過程的函數,不是工具定義的函數。

靜態政策看的是「這個工具在什麼條件下可以用」,一開始決定,全程不變,動態權限看的是「到目前為止發生了什麼」,因此同一個呼叫在不同時刻會得到不同答案。


上一篇
DAY26|靜態政策的代價,現階段動態做到哪些事
系列文
CaMeL 動態重擬定:讓 Agent 邊讀邊決定27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言