iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0
AI Security

AI Agent 憑什麼動手?30 天拆解 Agent Identity、Delegation 與 Authorization系列 第 12

Day 12|「幫我寄信」:Agent 到底取得了什麼授權?

  • 分享至 

  • xImage
  •  

Core Question

一句自然語言同意如何轉成對收件者、內容、次數與期限都有邊界的可執行 authority?

今天的問題:同意不是萬用 send_email

Alice 對 Support Agent 說:「把這次退款摘要寄給財務。」Agent 需要知道「這次」是哪個 task、財務是哪個已註冊收件群組、摘要允許哪些欄位,以及只能寄一次。若 consent 只換成 send_email scope,Agent 就能改寄外部地址、附上原始客戶資料,或在稍後重放同一 grant。

為什麼這不是傳統 IAM 問題

傳統 OAuth scope 多半描述一類 API 能力;Agent 的 Action 參數卻由模型在執行時生成,且可能受前一步查詢結果影響。自然語言 intent、使用者確認、formal grant 與真正送出的 message 不是同一份資料,必須透過 canonicalization 和 digest 連起來。

Threat / Failure Scenario

錯誤流程是:UI 顯示「允許寄信」,使用者按下同意後,Agent 取得 broad scope;模型將收件者改成 external@evil.test,把「摘要」擴成完整明細,Gateway 仍因 scope 有效而 allow。即使人曾同意,也沒有證據顯示人同意的是這個收件者與內容。

核心概念

  • Intent normalization: 把自然語言轉成結構欄位:recipient、content class、task、max count、expiry。
  • Consent ≠ authorization: 使用者確認是意圖證據;PDP 仍要驗證 actor、resource、policy 與當下狀態。
  • Parameter binding: grant 綁定 canonical Action digest,避免 approve-one-execute-another。
  • Replay resistance: jti、使用次數、expiry 與 idempotency key 必須在 PEP 消耗並記錄。

Architecture Pattern

Naive / Unsafe Design

UI 將「幫我寄信」換成永久 send_email scope;Agent 直接把任意 message POST 到 mail API,沒有結構化 constraints,也沒有將核准內容與執行內容比對。

Recommended Design

Intent service 產出待確認 grant。使用者確認後,Authorization service 簽發一次性、短效、audience-bound grant。PEP 對 Action 做 canonical JSON、計算 digest,只有 digest、recipient、content class、task 都吻合才呼叫 Tool。

Trust Boundary

User UI、Agent runtime、grant issuer、PEP/PDP、Mail Tool 各自分界。模型可提出 draft,但不能簽發 grant;Mail Tool 也不應接受 Agent 自帶的未驗證 recipient header。

Identity Flow

https://ithelp.ithome.com.tw/upload/images/20260917/201201516fYVdoEPGx.png

Authorization Decision Point

grant = {
    "sub": "alice", "task": "refund-12", "recipient": "finance@example.test",
    "content_class": "refund-summary", "max_count": 1, "jti": "g-1"
}

PDP 的 allow 條件是:sub 與 actor context 正確、task 尚未完成、recipient 與 class 完全符合、grant 未過期且 jti 未消耗。建議採用 RFC 9396 Rich Authorization Requests 的結構化請求思路;RFC 9449 DPoP 可在需要時綁定 sender,但不能取代 message 參數 policy。

小型 PoC

import hashlib, json

def digest(action):
    raw = json.dumps(action, sort_keys=True, separators=(",", ":"))
    return hashlib.sha256(raw.encode()).hexdigest()

action = {"recipient":"finance@example.test", "content_class":"refund-summary"}
grant = {"digest": digest(action), "uses": 0, "max_count": 1}

def execute(candidate):
    if grant["uses"] >= grant["max_count"]: return "deny: replay"
    if digest(candidate) != grant["digest"]: return "deny: parameters changed"
    grant["uses"] += 1
    return "allow: send"

assert execute(action) == "allow: send"
assert execute(action) == "deny: replay"
assert execute({"recipient":"external@evil.test", "content_class":"refund-summary"}) == "deny: replay"
print("binding and replay checks: PASS")

第三個案例特意在 replay 後執行;正式實作應對每次 candidate 先做 digest mismatch 檢查,並以原子操作消耗 jti。這個 PoC 證明「同意的 Action」必須是可比對的資料結構。

今天得到什麼

  1. 自然語言同意必須先被正規化,不能直接當 scope。
  2. recipient、content class、task、count 與 expiry 是 authority 的一部分。
  3. approval/grant 要與 canonical Action digest 綁定,防止參數偷換。
  4. 一次性 grant 仍需要 PEP、PDP 與 audit evidence 共同保護。

下一篇

Day 13 會問更棘手的問題:即使 Alice 本人能讀全部資料,Agent 是否仍應只讀必要欄位與筆數?

參考資料

未驗證事項:PoC 未實作時鐘、簽章與分散式原子 replay store;這些是 production 必須補上的 enforcement 細節。


上一篇
Day 11|Agent 是用自己的權限,還是使用者的權限?
下一篇
Day 13|使用者能看資料,Agent 就應該也能看嗎?
系列文
AI Agent 憑什麼動手?30 天拆解 Agent Identity、Delegation 與 Authorization14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言