過往的授權只驗證一件事:這個 Agent 當下有沒有權限執行該動作。一旦把「執行脈絡」放進來,問題的本質就變了——即便該動作完全合規,放在目前的任務目標與歷史軌跡裡,它還算不算合理的一步?
這兩者在存取控制中分屬完全不同的維度,前者是針對單次請求的單點判定,後者則是檢驗整條執行路徑的合理性。授權依據不再只是 capability,但要驗證這一步合不合理,最關鍵的資訊在執行 runtime 當下是調用不到的。
Day 11 的授權輸入寫出來是這樣:
Allow(a_t | capability_state_t)
capability_state_t 記錄的是 Agent 擁有的權限範圍,也就是它能調用哪些工具、工具各自能使用哪些資源的清單。這份設定在部署時就已固定,授權當下只是拿著當前的動作去查表。用 Saltzer 與 Schroeder 的話來說,這就是在落實「完全中介(complete mediation)」: 每一次請求都必須經過這個檢查點,對照既有狀態來判斷。
但它在結構上有個限制——它完全不管上下文與歷史紀錄。同一個請求能不能通過,不會因為前面執行過哪些步驟而有任何改變。Day 10 的來源標籤和 Day 12 的來源分級也是同樣的邏輯:標籤在外層就先標記好,授權端只負責比對。
要判斷「 這個動作在這條路徑上合不合理 」,輸入會多出好幾項。把它們列出來,只是為了看清這些資訊各自從哪來,不是說最後的系統一定照這個結構做:
AuthorizationInput_t = {
task_context, # 這次任務要達成什麼
capability_state_t, # Agent 有什麼權限
execution_trace_t, # 到目前為止實際做了哪些動作
current_action_t, # 現在要執行的這一步
legitimacy_reference # 什麼算「合理的執行路徑」
}
把這五項按「執行期拿不拿得到該權限」來分類,結果並不平均:
capability_state:授權政策裡本來就有,已經設定過了。current_action:執行當下就能被得知的。execution_trace:Agent 在跑迴圈時,逐步累積得到。task_context:得靠任務的上下文提供、或從上下文內容中擷取,成本較高但有辦法取得到。legitimacy_reference:沒有現成的來源。前四項執行期都能順利取得,它們回答的是同一種問題:發生過什麼運作流程、現在要繼續執行哪些流程。第五項回答的是另一種問題:這些授權裡哪些類型才算合理。授權的型態也跟著變了—— 它從「查一次清單、得到能不能授權的判斷結果」,變成「要對整條軌跡判斷合不合理」。 執行期看得到執行狀態內部細節,卻無法得知執行期間「應該」依據何種形式繼續運作。
剛剛的第五項分類結果不算在 capability_state中是因為合不合理根本不是歸類在 Agent 的屬性。同一個能力,在一個任務裡是必要的動作,在另一個任務裡卻沒有正當理由出現:
Capability(agent, read_customer_profile) = TRUE
Necessary(read_customer_profile, 修改帳單地址) = TRUE
Necessary(read_customer_profile, 查詢訂單狀態) = FALSE
能力沒變,Agent 沒變,變的是任務、以及這個動作在路徑上的位置。「必要與否」是「動作、任務、路徑」這三者湊在一起才成立的性質,不是單獨掛在動作上的一個標籤。任何只描述「Agent 有什麼權」的狀態,維度裡沒有任務、也沒有路徑,結構上就裝不下這三者。
這其實是最小權限(least privilege)更嚴格的一個版本。傳統講最小權限,是要求靜態的權限集合盡量小;但就算集合已經收到最小,read_customer_profile 在「查訂單」這條路徑上仍然是多餘的——它多餘的部分在於執行期間當下,而不是在已部署的設定裡。
要表達這種「相對於目前任務的最小權限」,授權就綁在任務和執行進度上。以任務為準的授權(例如 Atluri 與 Huang 的工作流程授權模型)把授權效力掛在任務執行狀態、而不是靜態角色上,正是為了這個。Day 5 談過權限給太多那是關於 Agent 能力的問題;這裡是在別的任務裡必要的能力出現在不該出現的位置。
Day 10、11、12 的授權能成立靠的是它們要比對的內容——標籤、能力集合、來源分級——這都是外部運作時先交給它的資料內容。授權流程只要查詢清單,不必自己找出「正確答案」。
execution_trace 把這個前提打破了。執行期記得住已經允許過的路徑,這不難;難的是記住路徑後,要拿這條路徑跟什麼內容作對比與分析。這裡可以借一個已知的結果來看清問題的位置:Schneider 對「可強制的安全政策」的分析指出,一個在執行期做監控的機制,能強制判定的是「安全性性質」—— 也就是一旦違反、就能在少量步驟中快速判定出的那類屬性特質 ——而且前提是這個規範能事前先寫成自動機制,把「哪種執行序列是合法的」定義出來。
執行期本來就在確認每一步是否符合規定,違規時可以攔截。缺的是能夠自動幫我們稽核的機制本身。軌跡記錄的是實際允許授權過的路徑,要做出判斷,得另外有一個機制負責協助我們稽核,而這個機制既不在軌跡裡,也不在能力清單中。前面幾層授權手上都有這份比對對象,到這一層才第一次得空著手。
拿實際通過執行的路徑去比對「已允許過的控制流」,這個立場和傳統的控制流完整性(control-flow integrity,CFI)一致。差別在那份「允許的控制流」的來源。
傳統程式:
程式結構 / 靜態分析 → 控制流圖(CFG)→ 合法的跳轉目標 → 執行期強制
Agent:
任務 + 脈絡 + 工具回傳 + 歷史 → 模型生出下一個動作 → 執行期轉移
傳統 CFI(Abadi 等人)的合法控制流,可以從程式結構和靜態分析建出一張控制流圖(CFG)。
這張圖通常是實際控制流的一個簡化版:執行期只要檢查每一次間接跳轉,有沒有落在圖上允許的目標裡,就能擋掉 ROP、JOP 這類「把程式裡原本就有的合法碎片,串連成攻擊」的手法。
CFI 也有無法攔截的部分:只要攻擊留在圖中允許的範圍內,比方說只調動資料或修改參數,沒有超出原控制流的職務範圍內的話,CFI 就看不到。這一點放到 Agent 上一樣成立——就算之後真的有了一份合法路徑,動作全走在合法路徑上、但參數或資料本身被動過手腳的情況,Agent 本身照樣看不到,那是關於來源問題的部分。
真正不一樣的地方在於 Agent 的下一個動作不是永遠固定的,而是模型在任務語意、工具回傳、環境狀態、歷史這些執行當下的脈絡下,臨時出現的。CFI 之所以能穩定創建是因為決定下一步的是程式碼結構、可以靜態分析;Agent 這邊決定下一步的是已讀取過這些資訊的模型,同一個 Agent、同一個任務,合理的路徑可能不只一條,都會隨情境改變。
所以 Agent 想做類似 CFI 的執行流程完整性,第一個卡住的不是「怎麼攔截一條不合法的執行路徑」,而是要先有一份「合法的執行路徑對照」可以拿來比對與攔截。這份參照從哪裡來是接下來要討論的。
Day 11 的授權可以縮成很短的一段:
action
↓
授權
↓
放行 / 擋下
它的特徵是每一次判斷都能單獨看。擋掉某個 action,不會因此在系統裡留下一個「這個 action 被擋過」的執行狀態、去改變下一次判斷;下一個 action 進來時,授權面對的還是同一種輸入。前後兩次判斷之間沒有牽連。
path-aware 的授權不一樣。它一開始就是看著整條執行路徑在判斷,而 enforcement 又會真的動手——阻止一步、收掉一個能力、把後續能走的範圍改掉。這一動手,流程就接了起來:
執行 ──→ 授權 ──→ 強制執行 ──→ 後續執行被改變 ──→ Agent 看到改變後的狀態
↑ │
│ ▼
└──── 新的授權 ←──── 新的執行 ←──── 重新規劃 ←──────────────────┘
前一次授權的結果,不再只是「這一步允許授權或拒絕授權」。它改掉的是下一步發生的條件:Agent 動作被攔截之後,會在不同流程繼續執行,而那個流程正是下一次授權要讀取並分析的內容。
到這裡,授權和前四節裡的樣子已經不同。前面它站在旁邊看著執行、做出判決;現在它的判決會改變接下來執行的走向。授權、enforcement、執行三者不再是可以完全切開來看的階段,而是繞成一個迴圈:判決改變後續狀態,後續狀態又回來成為下一次判決的輸入。Agent 被拒絕後可能重新規劃,規劃出新的 action,新的 action 又進到授權。
這個迴圈裡會冒出哪些行為,目前只能說是可能,不能當成定論:Agent 可能會重試同一步、可能改走另一條路去達成同一個目的、可能因為某個能力權限無法使用,而被迫轉換成其他做法,也可能在一次任務裡反覆觸發授權與 enforcement。這些都還沒有被此範圍中的任何資料證明一定會發生,只是迴圈一旦成立,它們就進入了要考慮的範圍。
所以 path-aware 的授權一旦真的介入執行,就不太能再只當成一個「判斷關卡」來理解。它不只是在描述或判斷執行,它本身已經是執行裡的一個控制環節——它會塑造自己下一次要判斷的那條路徑。要不要因為偵測到偏離就執行、要完成到什麼樣的程度、以及這樣執行後會不會反過來把後續執行結果推導至更難以判斷的0地方,這部份我們之後有機會也會討論。
授權從「這個 Agent 有沒有權」,變成「這個有權的動作,在目前的任務和路徑上合不合理」之後,需要的輸入從單一的能力,擴成任務內容、執行軌跡、當前動作這幾樣執行期拿得到的東西。要強制「一整條軌跡成不成立」這種性質,機制上是已知可行的——執行期監控本來就能強制安全性性質——但那套結果有個前提,得先有一台把「合法序列」定義出來的機制。真正決定「合理」的那份參照資料,執行期沒有現成來源:因為軌跡只會告訴它發生過什麼動作經歷,而不會告訴它什麼參照資料才是正確且可使用的。
因此綜上所述,授權驗證的必要性與「動作、任務、路徑」有關,而非 Agent 本身,這決定了參照資料是沒辦法從能力及狀態清單推導出來的。
感謝大家今日份的閱讀。