iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0

Core Question

靜態 API Key 能否證明是哪個 Agent instance、代表誰,以及此刻為何執行?

今天的問題

一個客服 Agent 使用 AGENT_API_KEY 呼叫工單 Tool。Key 被放在 image 的環境變數,後來被錯誤 log 帶出。攻擊者拿到它後,可以從另一台機器重放請求;Tool 仍只看見「有效 key」,無法分辨原本的 instance、User 或 Task。即使每個 Agent 一把 key,也只改善 attribution,沒有 expiry、audience 或 sender binding。

為什麼這不是傳統 IAM 問題

API Key 通常回答「持有秘密者能否進入 API」。Agent authorization 還要回答「哪個 runtime 代表哪個 subject,在什麼 Task、對哪個 resource 執行」。靜態 bearer secret 把這些 context 壓成一個可複製字串,不能把模型提出的 Action 綁在委派上。

Threat / Failure Scenario

Naive / Unsafe Design

所有 Agent 共用一個長效 key;Tool 以 key 對應 role,且不檢查 destination 或 Task。洩漏後,攻擊者可查資料、偽造 User attribution、持續重試,撤銷只能影響所有 Agent。

Recommended Design

把 API Key 限定為 bootstrap 或低風險、內網、可快速輪替的 credential。真正呼叫 Tool 時,以受信任 workload identity 取得短效、audience-bound、至少 scope/task-bound 的 token;高價值 Action 再要求 sender-constrained proof。Key 仍可作緊急相容層,但不能是唯一的 Agent identity。

核心概念

Property shared API key per-Agent key short-lived bound token
instance attribution 部分 可精確
expiry / blast radius 通常無 / 大 可做但常被忽略 預設短
audience 通常無 可自訂 可驗證
replay resistance 可配合 sender constraint
delegated subject/task 外部另傳,易偽造 外部另傳 可由 issuer 綁定

Architecture Pattern

https://ithelp.ithome.com.tw/upload/images/20260912/20120151sESivzjjTD.png

Trust boundary 在 runtime、broker/Gateway 與 Tool 之間;Tool 不應接受未經 PEP 的長效 key。Authorization Decision Point 在 PDP,不能把 key 的存在當成 allow。RFC 6750 定義 bearer token 的核心風險是持有者即可使用;RFC 9700 建議 sender-constrained 與 audience restriction 來降低重放和 redirect。

小型 PoC

import time, hmac, hashlib

STATIC = "shared-secret"
now = 1_000

def static_call(key, action):
    return hmac.compare_digest(key, STATIC)  # 重放沒有時間或 audience

def short_token(actor, aud, exp, nonce):
    body = f"{actor}|{aud}|{exp}|{nonce}"
    sig = hmac.new(b"issuer", body.encode(), hashlib.sha256).hexdigest()
    return body + "|" + sig

def verify(raw, expected_aud, t):
    actor, aud, exp, nonce, sig = raw.split("|")
    body = "|".join(raw.split("|")[:-1])
    good = hmac.compare_digest(sig, hmac.new(b"issuer", body.encode(), hashlib.sha256).hexdigest())
    return good and aud == expected_aud and int(exp) > t

assert static_call(STATIC, "delete") and static_call(STATIC, "delete")
tok = short_token("agent/i-2", "tool://tickets", now + 30, "n1")
assert verify(tok, "tool://tickets", now + 1)
assert not verify(tok, "tool://tickets", now + 31)  # 舊 token 過期
assert not verify(tok, "tool://billing", now + 1)   # audience 不符
print("static replay: accepted; short-lived expired/audience checks: rejected")

這是 HMAC 示意,不是生產 JWT 實作;生產環境要用標準 token profile、金鑰保護與 issuer rotation。PoC 實際驗證了靜態 key 可重放,短效 token 在過期與錯誤 audience 被拒絕。

成功與拒絕都應留下 actor、credential id、audience、expiry、Task、Action digest、policy version 和 deny reason;不要把 API Key 本身寫入 log。

今天得到什麼

  1. API Key 證明的是 secret possession,不等於 Agent instance identity。
  2. per-Agent key 可改善歸責,但無法自然表達 User、Task、expiry。
  3. 短效與 audience-bound credential 能縮小重放和 blast radius。
  4. 最終 Tool Call 仍需 subject + actor + Action 的 policy decision。

下一篇

既然長效 key 不理想,下一篇處理生命週期:Agent 每次啟動,是否應取得不同的 credential?

參考資料


上一篇
Day 06|Agent 呼叫 Tool 時,Tool 到底要認誰?
系列文
AI Agent 憑什麼動手?30 天拆解 Agent Identity、Delegation 與 Authorization7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言