從零構建基礎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標誌。