從零構建基礎AI代理:安全性第三部分
本文繼續加強AI代理的安全性,實現三層策略門(路徑範圍、Shell黑名單、SSRF防護)、針對破壞性操作的始終確認模式、最小權限原則(通過工具白名單)以及資源/成本控制以防止失控循環。
在上一部分中,我們開始通過人類參與循環來填補安全漏洞:使用Docker沙箱來隔離失控命令、提示注入防禦使模型不再信任工具輸出作為指令,以及模式驗證確保格式錯誤的工具調用不會被執行。在本部分中,我們完成剩餘工作。我們將通過路徑範圍、Shell黑名單和SSRF防護來強化工具策略門,實施資源和成本限制以防止卡住的循環無限運行,從容器環境中清除秘密,並添加審計日誌和緊急停止開關,以便記錄每個決策並能夠在飛行中終止任何會話。
工具策略強化
在“人類參與循環與安全性”部分中,check_permission是一個單一函數:讀取工具和規劃工具始終允許,寫入工具在工作目錄內允許(在acceptEdits模式下),其他所有操作需要詢問。那是基於模式的決策。
現在我們添加一個策略門,它在模式決策之前運行。該門有三層:
路徑範圍: 每個路徑參數都被解析(處理相對路徑、符號鏈接和..遍歷),如果逃逸項目工作目錄則被拒絕。這阻止代理訪問~/.ssh/id_rsa、/etc/passwd或項目樹之外的任何內容。
Shell策略: 每個run_bash命令都通過危險模式的正則黑名單(fork炸彈、dd、mkfs、重定向到/etc/等)和代理絕不應調用的二進制文件令牌級黑名單(sudo、nc、curl、chmod、docker等)進行篩查。這捕捉到破壞性和數據外泄命令。
SSRF防護: 服務器端請求偽造是一種攻擊,其中服務器端進程被誘騙向不應訪問的內部資源發出請求。在代理上下文中,提示注入可能使webfetch訪問內部服務或雲元數據端點。防護解析URL的主機,檢查結果IP是否屬於迴環、鏈路本地、多播以及RFC1918私有範圍,並阻止它們。
def check_tool_policy(
tool_name: str,
args: dict[str, Any],
working_dir: Path,
) -> tuple[bool, str | None]:
"""運行所有策略層。返回 (allowed, reason)。
由 ``agent.check_permission`` 在基於模式的決策之前調用。
返回 False 表示硬阻止,任何模式都無法覆蓋。
"""
# 第1層:路徑範圍。
ok, reason = check_path_scope(tool_name, args, working_dir)
if not ok:
return False, reason
# 第2層:Shell策略。
if tool_name == "run_bash":
ok, reason = check_shell_policy(args.get("command", ""))
if not ok:
return False, reason
# 第3層:Web/SSRF策略。
if tool_name == "webfetch":
ok, reason = check_web_policy(args.get("url", ""))
if not ok:
return False, reason
return True, None路徑範圍
舊的檢查僅在寫入工具上運行。現在,檢查推廣到每個使用路徑的工具:read_file、glob_files、grep、write_file、edit_file。每個工具的路徑參數被解析(處理相對路徑、符號鏈接和..遍歷),如果逃逸工作目錄則被拒絕。
Shell策略
run_bash是最危險的工具,因此它有自己的篩查。每個命令運行兩個檢查。首先,危險模式的正則黑名單;然後,命令被詞法解析,每個令牌與黑名單二進制文件比對。
Web策略(SSRF防護)
webfetch針對服務器端請求偽造進行篩查。雲元數據端點、本地主機和私有IP範圍均被阻止。
始終確認模式
在硬策略門之上,某些模式足夠危險,無論權限模式如何,都需要明確確認。這些是不可逆/數據外泄類操作。check_permission函數現在具有三層結構:硬策略門、始終確認、模式決策。始終確認返回(bool, reason),以便此層攜帶其自己的特定原因。
最小權限原則
另一個控制適合此處:一個--tools CLI標誌,接受逗號分隔的工具允許列表。檢測器過濾進程內註冊表和暴露給LLM的模式,因此模型甚至看不到它無法調用的工具。例如:python agent.py --tools read_file,glob_files,grep,run_bash 如果知道代理永遠不需要寫入文件,可以通過限制允許的工具來極大地縮小危險爆炸半徑。
資源與成本控制
我們將向檢測器添加一些資源和成本控制,以限制代理在我們不注意時失控。
硬迭代上限
IterationCaps跟蹤兩個計數器:turns(每次用户回合內的LLM響應次數,默認40,可通過--max-turns覆蓋)和tool_calls(每次工具調用遞增,默認200,可通過--max-tool-calls覆蓋)。當任一計數器超過上限時,循環終止,並向用户返回一條消息,要求他們決定是否繼續。對於總是啓用此功能的用户,可以使用--iterations boundless標誌。