13.2 工具安全與權限控制#
為什麼工具安全至關重要#
在第 13.1 節中,我們看到提示注入可能導致 LLM 被操控來執行非預期操作。但這一切的前提是:Agent 確實擁有可以造成傷害的工具。一個只能輸出文字的 LLM,最壞情況是產生不當內容;但一個能呼叫 Bash、讀寫檔案、執行金流交易的 Agent,一旦被劫持,造成的損害就可能是真實世界的損失。
因此,工具安全(Tool Safety)是 Agent 系統設計中不可妥協的核心議題。
故障安全預設值(Fail-Safe Defaults)#
所有能力預設關閉,是工具安全的第一原則。
新的 Agent 系統上線時,不應自動綁定任何具有寫入能力或外部副作用的工具。每個工具都需要經過明確的授權流程才能啟用。這與傳統資安中的「預設拒絕」(Default Deny)原則一致。
實務上的實作方式:
- 工具註冊表(Tool Registry):所有可用工具集中管理,每個工具附帶元資料,包括用途描述、風險等級、所需權限。
- 啟用清單機制:Agent 需要在設定中明確列出要啟用的工具,未列出的工具一律不可呼叫。
- 風險分級:
| 風險等級 | 工具類型 | 範例 | 啟用條件 |
|---|---|---|---|
| 低 | 只讀查詢 | 網頁搜尋、唯讀資料庫查詢 | 預設啟用 |
| 中 | 本地操作 | 檔案讀寫、Shell 執行 | 需明確啟用 |
| 高 | 外部副作用 | 發送郵件、金流交易、API 寫入 | 需逐次確認 |
| 極高 | 不可逆操作 | 刪除資料庫、撤銷部署 | 需人類審批 |
權限最小化(Principle of Least Privilege)#
每個工具應只擁有完成其功能所絕對必要的最小權限。例如:
- 資料庫查詢工具只能 SELECT,不能執行 DROP 或 DELETE。
- 檔案工具只能操作特定目錄(如
/workspace/),不能存取/etc/或~/.ssh/。 - 網路工具只能連線白名單上的域名,不能任意發出 HTTP 請求。
在實作上,這通常透過作業系統層級的機制來強制執行(如 Linux 的 namespace、seccomp、AppArmor),而非僅依賴模型自律。
Sandbox 與隔離環境#
為什麼需要沙盒#
即使做了權限最小化,仍然可能有零日漏洞或未預期的權限提升路徑。沙盒(Sandbox)是最後一道防線:讓工具在隔離環境中執行,即使被攻破,影響範圍也受到限制。
沙盒實作層次#
- 語言層沙盒:如 Python 的 RestrictedPython,限制可使用的內建函式。
- 程序層沙盒:使用 Linux namespace、seccomp-BPF 限制系統呼叫。
- 容器沙盒:使用 Docker/gVisor/Kata Containers 隔離檔案系統與網路。
- 虛擬機沙盒:最強隔離,但啟動成本較高,適合高風險操作。
工具沙盒示意圖#
flowchart TB
subgraph User
A[使用者] -->|請求| B[Agent 調度器]
end
subgraph Agent Core
B -->|決策| C{風險評估}
C -->|低風險 自動執行| D[工具呼叫]
C -->|高風險 需確認| E[人類審批佇列]
E -->|核准| D
E -->|拒絕| F[取消]
end
subgraph Sandbox Layer
D --> G[沙盒執行環境]
G --> H[檔案系統\n唯讀掛載 + tmpfs]
G --> I[網路\n白名單域名]
G --> J[系統呼叫\nseccomp 過濾]
G --> K[資源限制\nCPU / 記憶體 / 超時]
end
subgraph Output Validation
G -->|原始結果| L[輸出驗證器]
L -->|通過| M[回傳 Agent]
L -->|異常| N[攔截 + 告警]
end
M --> O[回應使用者]存取控制清單(ACL)#
對於每一種工具的每一個操作,都應有明確的存取控制清單(Access Control List)。在 Agent 系統中,ACL 可以同時作用於三個層面:
Agent 層 ACL#
不同 Agent 角色擁有不同的工具存取權限。例如:
- 客服 Agent 只能讀取訂單資料,不能修改。
- 部署 Agent 只能觸發 CI/CD pipeline,不能直接操作伺服器。
- 研究 Agent 只能搜尋網頁和讀取文件,不能執行任意程式碼。
工具層 ACL#
同一個工具對不同 Agent 或不同情境有不同權限。例如檔案系統工具:
- Agent A 只能讀寫
/workspace/agent_a/。 - Agent B 只能讀寫
/workspace/agent_b/。 - 所有 Agent 都不能存取
/workspace/shared/secrets/。
操作層 ACL#
同一個工具的同一個操作,根據參數有不同的風險。例如 SQL 工具:
- SELECT 語句:自動執行。
- INSERT/UPDATE 語句:需日誌記錄。
- DELETE 語句:需人類確認。
- DDL(CREATE/DROP):禁止執行。
AI 使用高風險工具的安全設計案例#
以 Bash 工具為例,說明如何在實務中結合上述原則:
class BashTool:
def __init__(self):
self.allowed_commands = ["ls", "cat", "grep", "find", "wc"]
self.blocked_patterns = ["rm ", "sudo ", "curl ", "wget ", "| sh"]
self.max_execution_time = 30 # 秒
self.workspace_root = "/workspace/"
def execute(self, command: str, agent_id: str) -> ToolResult:
# 1. 路徑正規化:防止路徑穿越
resolved = os.path.realpath(command)
if not resolved.startswith(self.workspace_root):
return ToolResult(blocked=True, reason="路徑超出允許範圍")
# 2. 命令白名單檢查
base_cmd = command.split()[0]
if base_cmd not in self.allowed_commands:
return ToolResult(blocked=True, reason=f"命令 {base_cmd} 不在白名單")
# 3. 危險模式過濾
for pattern in self.blocked_patterns:
if pattern in command:
return ToolResult(blocked=True, reason="偵測到危險模式")
# 4. 在沙盒中執行(帶超時)
result = sandbox.run(command, timeout=self.max_execution_time)
# 5. 輸出驗證
if contains_sensitive_info(result.output):
result.output = redact(result.output)
return result
以金流工具為例,安全設計更為嚴格:
- 每筆交易都需人類在前端 UI 確認,Agent 只能「建議」交易,不能直接執行。
- 交易金額設有上限,超出部分需二次授權。
- 所有交易記錄寫入不可變更的審計日誌。
- 實作速率限制(Rate Limiting),防止被提示注入操控後大量轉帳。
本章小結#
工具安全是 Agent 系統從「能做事」到「安全地做事」的關鍵跨越。核心原則包括:故障安全預設值(所有能力預設關閉)、權限最小化、Sandbox 隔離、以及精細的 ACL 控制。這些原則需要同時作用於 Agent 層、工具層、操作層,形成縱深防禦。記住:模型的智慧無法取代架構的約束——安全不能靠「希望模型不要做壞事」來保證。
想一想#
- 如果你的 Agent 需要執行 SQL 查詢,你會如何設計 ACL 來區分 SELECT、INSERT、UPDATE、DELETE 的權限?
- 沙盒環境會帶來效能開銷。在需要即時回應的場景(如客服對話),你會如何在安全與效能之間取捨?
- 設計一個「Agent 可以發送郵件」的工具安全方案:需要哪些層級的確認機制?如何防止 Agent 被提示注入後發送垃圾郵件?