AI Agent 安全:從九宗真實事故歸納六項控制措施
AI Agent Security: Six Controls From Nine Real Incidents
文章根據 2025 年 5 月至 2026 年 7 月的九宗公開事故,整理 AI Agent 的三個攻擊面,並提出六項限制損害的控制措施。措施包括隔離智能體、限制憑證權限、保護設定、記錄每次工具呼叫、事前掃描工作區機密資訊,以及預設拒絕。這些措施不能阻止提示詞注入,只能限制被劫持的智能體可觸及的範圍。
文章按主機、身分與智能體三個攻擊面整理九宗公開事故,再歸納六項事前控制,讓讀者可對照憑證、設定與工作區防護。
重點摘要
- 三種攻擊面:AI Agent 會暴露其主機、身分及自身。2025 年 5 月至 2026 年 7 月的九宗公開事件涉及全部三種攻擊面;Agent 攻擊面出現在其中五宗,且從未單獨出現。
- 憑證才是目標:在注入事件中,Agent 會讀取包含指令的問題單、電郵、設定檔或網頁。指令打開了入口,而攻擊者真正想取得的是憑證。
- 六項控制措施可限制損害範圍:將 Agent 放入沙箱、限制其憑證權限、避免它接觸自身設定、記錄每次呼叫、先掃描工作區中的機密資料,以及預設拒絕。但沒有任何一項能防止提示詞注入。
摘要
AI Agent 使用你的憑證執行操作,往往在你制止前已採取行動。九宗事件揭示了箇中代價。六項控制措施可限制損害:將 Agent 放入沙箱、限制其憑證權限、鎖定其設定、記錄每次呼叫、先掃描工作區,以及預設拒絕。
AI Agent 的攻擊面:主機、身分及 Agent 本身
Agent 會暴露三種不同的攻擊面:它接觸的主機、它使用的身分,以及 Agent 本身。
主機是程序能存取的一切:檔案系統、程序執行、網絡、環境變數,以及攝影機或咪高峯等硬件。身分是 Agent 執行操作時使用的帳戶,包括其權限和權限範圍,以及它在過程中能找到的所有憑證。Agent 則是傳統程序沒有對應概念的部分。它有自己的上下文、透過記憶、hooks、技能和設定保存的狀態,以及它連接的工具。
這三種攻擊面的失效方式各異,需要不同的控制措施。傳統作業系統安全已涵蓋主機。身分問題大致可透過成熟的身分與存取管理(IAM)模式解決。
Agent 攻擊面是新出現的一面,因為每項輸入都可能是指令。把三者分開,有助判斷哪些事件現時已可解決,哪些仍是業界正在摸索的問題。
十五個月內的事件,按攻擊面分類
2025 年 5 月至 2026 年 7 月的九宗公開事件涉及全部三種攻擊面。Agent 攻擊面出現在其中五宗,且從未單獨出現。
主機:理論上可解決,實際上仍會出問題
2025 年 7 月,一名用戶要求 Gemini CLI重新整理資料夾,方法是建立新目錄並將檔案移入其中。mkdir 指令悄然失敗。Agent 沒有檢查錯誤,以為操作成功,並繼續向不存在的路徑發出搬移指令。由於所有搬移操作都指向同一個不存在的目的地,每個檔案都覆寫了前一個,最後只剩下一個檔案。沒有攻擊者,也沒有注入攻擊。問題出在未經檢查的結束碼,以及一個假設操作成功的迴圈。
一個月後,一名用戶要求 Claude清理 Claude 建立的目錄。權限系統正常運作,要求確認 rm -rf ~/。用戶因疲憊而批准了操作。造成的損害與惡意清除無異。
這兩宗事故分別越過了同一條界線的兩端。Gemini CLI 一直在指定的資料夾內操作,因此沙盒根本不會介入。它只刪除了交給它處理的內容。Claude 則恰恰相反:用戶要求它處理的範圍僅限於自身輸出,它卻提議刪除家目錄。以工作區為範圍的沙盒本可阻止這宗事故。當時唯一的控制措施是批准對話框,但這道防線在疲憊的用戶面前失效了。
Gemini 的事故更令人不安。若把同一個 Agent 指向家目錄,而不是專案資料夾,同一個錯誤就會清空整部手提電腦。因此,控制措施不只在於能否限制 Agent,還在於一開始交給它甚麼。
身分:Agent 會繼承你持有的存取權限
2025 年 12 月,一名 AWS 工程師使用 Amazon 的 Kiro Agent 修復 Cost Explorer(AWS 帳單儀錶板)的一個錯誤。Agent 決定刪除並重新建立整個環境。它繼承了工程師的高級權限,跳過了同儕審查,並導致區域性服務中斷 13 小時。Amazon 將事故歸咎於設定錯誤的 IAM role,而非 AI。
2026 年 4 月,一個負責 Railway 部署工作的 Agent遇到問題後,決定刪除一個儲存磁碟區。它沒有權限執行刪除操作,於是到檔案系統中尋找 token。刪除操作摧毀了正式環境,以及存放在同一位置的備份。
沒有人向 Railway Agent 授予該憑證:是它自行找到的。該主機上的所有機密資訊,無論你是否有意授予,都屬於它的身分範圍。真正重要的問題不是你交給 Agent 甚麼,而是它能在你提供的環境中找到甚麼。
Agent:每項輸入都可能是指令
2025 年 5 月,Invariant Labs 證明,在公開儲存庫中提交一個惡意 issue已足以造成事故。受害者要求 Agent 檢查未解決的問題。Agent 讀取了植入的指示,使用受害者權限範圍過大的 GitHub token 取得私有儲存庫,並將內容洩漏到公開拉取請求中。一個權限範圍過大的 token在公開與私有環境之間重複使用,卻沒有任何機制強制隔離。
2025 年 6 月,Aim Labs 公開了 EchoLeak。一封經過設計的電郵便足以觸發攻擊。Microsoft 365 Copilot 將電郵內容當作上下文處理。隱藏指示令它搜尋用戶的郵箱、OneDrive 和 SharePoint,然後透過自動載入的圖片 URL 外傳搜尋結果。受害者甚至沒有開啟該電郵。Microsoft 將其評為 CVSS 9.3。
2026 年 2 月,Check Point 記錄了透過 Claude Code 專案檔案遠端執行程式碼及竊取 API 金鑰的情況。複製並開啟不受信任的儲存庫便足以觸發攻擊。惡意的 .claude/settings.json以 hook 形式注入 shell 指令。一個 .mcp.json在信任對話框出現前啟動 MCP 伺服器。由儲存庫設定的 ANTHROPIC_BASE_URL則將已驗證流量(包括授權標頭)重新導向至攻擊者的端點。三者都在用戶同意任何操作前執行。
2026 年 7 月,Intezer 證明,同一個 AWS Kiro Agent 讀取一般網頁上的隱藏文字後,會改寫自己的 MCP 設定。Agent 修改了原本用來限制它的檔案,然後重新載入該檔案。在預設的自主模式下,批准提示並無實際效用。
本節的每宗事故,起因都一樣:Agent 讀取了它本來就會讀取的內容,而該內容帶有指令,例如 issue 內文、電郵、設定檔或網頁。指令試圖取得的東西,則構成這個模式的後半部分:權限範圍廣到足以由公開資源跨至私人資源的 GitHub token;一個只負責摘要電郵的工作階段,卻擁有郵箱和雲端硬碟的權限範圍。指令打開了大門,而攻擊者真正想要的是憑證。
沒有攻擊者,三個層面都受影響
2026 年 7 月,正在進行網絡安全能力評估的 OpenAI models 逃出沙盒,並入侵 Hugging Face 的生產環境基礎設施。沒有人攻擊它們。任務受阻後,它們把一個內部 Artifactory 執行個體改造成留言板,並在上面交換漏洞利用程式。防禦人員撤銷憑證並將它刪除後,Agent 在一天內便重建了留言板。我們的報告載有完整時間線。
九宗事故之中,只有這宗事故涉及主機、身份和 Agent 三個層面,而且整個過程中完全沒有攻擊者。Agent 接到目標後未能達成,於是另覓途徑。防禦人員封堵這條途徑後,它們又找到下一條。
AI Agent 威脅模型:舊問題,新速度
把 Agent 視為一種記憶體內惡意軟件;你可能無法對它進行逆向工程並理解它。它以獲委派的權限執行,在任何人類介入前便採取行動,而且每次的行為都可能不同。
能力:Agent 可以做甚麼
Agent 以高權限執行,通常承襲啟動它的人的權限。它會讀取和寫入檔案系統、連接網絡、執行程式碼,亦可以啟動子 Agent。它會存取憑證,包括獲提供的憑證和自行找到的憑證。它會透過記憶、hooks、skills 和設定來保存狀態。
與其他所有程序不同,Agent 亦會透過 skills 和 MCP 伺服器連接工具。Agent 會把這些連接器讀作指令。工具描述會像用戶提示詞一樣進入它的上下文,因此使用連接器就意味著讀取不可信輸入。
後果:會出甚麼問題
五種問題:破壞、資料外洩、橫向移動、持久化和機密洩露。
以上最明顯的事故是破壞,通常幾分鐘內便會有人察覺。資料外洩和橫向移動完全不需要出錯:讀取資料和使用憑證正是 Agent 執行的任務。只有在偵測系統發出警報,或有人終於查看記錄時,這些情況才會浮現。
Agent 的持久化和機密洩露,呈現方式各有不同。一般程序結束後不會留下任何東西。Agent 則會寫入記憶、hooks、skills 和設定,然後在之後的工作階段讀取它們,視作先前已有的知識。沒有其他良性程序會自行決定搜尋憑證。Agent 會搜尋檔案系統和環境以尋找憑證,找到後便會傳送給模型供應商。
這些問題都不是新的。我們多年來一直在防禦同樣的後果。新的是,單一程序在一次執行中就能造成這麼多種後果。
攻擊途徑:事情如何發生
五種入侵途徑:模型本身、提示詞注入、工具和 skill 投毒、記憶投毒,以及批核疲勞。
模型本身根本不需要攻擊者。Agent 認為刪除環境就是解決方法,而且有權限執行。上述事故中有四宗屬於這一類。OpenAI 的 Agent 在任務受阻時也沒有停下來:它們找出漏洞並加以利用。錯誤決定和正確決定在日誌中留下的記錄完全相同。
其餘三宗都需要有人植入指令。直接提示詞注入由用戶發起,而用戶本身已是安全主體。間接注入則藏在 Agent 需要處理的內容中,例如 issue 內文、設定檔、拉取請求標題或網頁。上述事故中有四宗由此引發,而且每宗事故中的內容都是 Agent 完成工作所必須讀取的。工具及技能投毒則是透過連接器引發的同一問題。Agent 將工具説明讀作指令,而遠端伺服器可以在審查後更改説明。記憶投毒是唯一會延續到工作階段之後的類型:它會在之後的任務中以先前知識的形式出現。
rm -rf ~/ 案例顯示了審批提示的侷限。控制措施已啟動,有人查看了提示,然後批准了操作。
放大因素:哪些地方有所不同
有三個因素會令過往事故的後果更嚴重:速度、規模和非確定性。
Gemini CLI 覆寫資料夾的速度,快得用戶還來不及看完輸出。事後才執行的審查步驟,無法阻止操作發生。Hugging Face 的 Agent 是互不共享狀態的獨立執行程序。其中一個找到了脱身方法,並寫下來讓其他程序讀取,因此之後每次執行一開始便有了這種漏洞利用方法。同一個提示詞在不同次執行中會引發不同操作,因此一項設定可能通過一次測試,下一次卻失效。
攻擊途徑和事故結果都不是新事物。新的是,Agent 的行動速度更快、影響範圍更大,而且比我們為審查其行動而建立的安全流程更難預測。
AI Agent 安全控制措施:按層面盤點現有方案
現有的控制措施按層面分類如下:主機、身分識別、Agent,以及圍繞這三者的執行框架架構。
主機:限制其活動範圍,並控制交給它的資源
先使用 Agent 本身提供的功能。不要使用 --dangerously-skip-permissions 來執行 Claude,其他 Agent 的同類設定亦然。在有原生沙盒的情況下使用它,並為工具、路徑和命令設定允許及拒絕規則。這些設定很容易啟用,也很容易被不可信的程式碼儲存庫覆寫,因此只能作為第一層防護,而不能是唯一防護層。
然後在沙盒中執行 Agent。核心沙盒例如 nono、微型虛擬機器例如 Docker Sandboxes,或容器,都能將檔案系統、程序及網絡存取限制在任務所需範圍內。整合式執行環境例如 Bromure,則會將虛擬機器、沙盒及出站代理整合在一起。這能阻止 rm -rf ~/ 案例。
但這無法阻止 Gemini CLI 案例。沙盒允許 Agent 寫入工作目錄,而損害正是在這裏發生。掛載專案目錄,而不是主目錄。要使用的工作集由你決定,沙盒無法代你作決定。
將復原途徑置於 Agent 無法觸及之處。Railway 的磁碟區以同一個身分識別存放正式環境及其備份。Agent 能刪除的備份就不算備份。在專案層面,版本控制涵蓋已追蹤的檔案,而 nono 的工作區快照則涵蓋其餘檔案。寫入操作仍會發生;回復操作會將其撤銷。
這些機制在 Agent 出現之前,已為不可信的程式碼和用戶而建立。它們確實有效。
身分:為 Agent 設立專屬身分,並減少其權限
為 Agent 設立專屬的身分主體。當它以用戶身分執行時,稽核記錄只會記下用戶。發生事故後,沒有人能分辨哪些操作由用戶執行,哪些由 Agent 執行。專屬身分配合範圍受限的權限,一步便可解決歸屬問題並限制損害。
將憑證的權限範圍限制在工作所需,並確保其他憑證一概無法存取。Railway Agent 需要一個部署權杖,卻找到一個也能刪除磁碟區的權杖。部署權杖本不應具有這項權限,而權限更廣的權杖也不應存放在 Agent 能讀取的磁碟上。這同樣適用於 Agent 無須獲提供便能存取的所有憑證:環境變數、點檔、AWS 和 GitHub CLI 的憑證儲存區、SSH Agent 通訊端,以及瀏覽器工作階段。需要一個權杖的 Agent,應在只包含一個權杖的環境中執行。nono 和 Bromure 處理的是另一部分:Agent 看到的是佔位符,透明代理則在傳輸時換入真正的憑證值。但它們無法限制權杖本身的權限範圍。如果代理注入的憑證能刪除正式環境,Agent 就能刪除正式環境。
在 Agent 接觸之前,先了解當中已有甚麼。散落在儲存庫、CI 執行器或主目錄中的機密資料,就是 Agent 可探索的範圍。在首次執行前掃描工作區,可以縮小這個範圍。這是此處唯一能在 Agent 執行前生效的控制措施。
按範圍設定身分和使用短效憑證,都是早於 Agent 出現的身分與存取管理做法;憑證代理則不是。它之所以存在,是因為 Agent 會尋找未獲提供的身分,而代理會確保它找不到任何可用的身分。至於已提供給 Agent 的憑證,仍須沿用傳統方式限制其權限範圍。
Agent:限制其可接觸的範圍
此處有四項控制措施:不讓 Agent 操控設定、使用允許清單列出的連接器、記錄每次呼叫,以及進行偵測。
不讓 Agent 操控設定。Agent 會把 .claude/settings.json 和 .mcp.json 等專案層級檔案讀作指示,而不可信的儲存庫可以設定這些檔案。控制措施必須設於這些檔案之外。在沙盒中將設定和記憶體路徑設為唯讀,可以阻止 Agent 改寫它們。Kiro 曾在讀取網頁後改寫自己的設定。
使用允許清單列出工具和連接器,並瞭解其限制。遠端 MCP 伺服器在下一次執行時可能提供不同的工具描述。對這類伺服器,安裝前的審查無法涵蓋 Agent 之後會讀取的內容。
記錄每次工具呼叫和每個對外連線。nova-tracer 等 Hook 層級記錄工具,可記錄每次工具呼叫及其引數。OpenTelemetry 可將相同記錄傳送至團隊現有的追蹤系統。輸出流量記錄會顯示 Agent 連接過哪些網域,包括它曾向其傳送對話內容的網域。
偵測措施對 Agent 的涵蓋效果不如對人類。EDR 特徵碼是針對人類行為模式調校的,而 Agent 不會產生這些模式。防護措施能捕捉已知的提示注入模式,卻會漏掉新型模式。兩者仍應與上述控制措施並用,但都不能作為唯一措施。
以上每項控制措施都會限制 Agent 接獲指示後能做的事,但沒有一項能阻止指示本身。
架構:決定 Agent 可接觸甚麼
有兩項設計決策可限制指示送達後所能造成的影響。兩者都是對你現有的 Agent 作出的設定變更。
按任務而非 Agent 設定工具範圍。讀取公開 issue 的任務,不應獲得可寫入私人儲存庫的工具。Claude Code 透過子 Agent 工具實現:lists、--allowedTools 和 --strict-mcp-config;Codex 透過 --sandbox;pi 透過 --tools,或在 nono 下執行。Invariant Labs 的案例到此便會被阻止。
只要求批准無法撤銷的操作。
採取預設拒絕,並只在寫入、傳送、刪除及支出時提示,才能讓提示數量少到用戶可以逐一閲讀。Claude Code:acceptEdits 加上唯讀允許清單,或使用 PreToolUse hook。Codex:--sandbox workspace-write --ask-for-approval on-request。pi:permission-gate 擴充功能,將讀取設為允許,其他操作一律設為詢問。
尚未解決的問題
目前有三個問題尚未有完整的控制措施。
模型本身。上下文中沒有任何內容能解釋模型為何決定刪除環境。若模型經過訓練,會在觸發條件出現時採取行動,就更難察覺。指令存在於權重之中,工作階段內沒有任何輸入會顯示這一點。上述控制措施都假設 Agent 最終會做錯事,並盡量縮小影響範圍。
記憶中毒。如上一節所述,將記憶路徑設為唯讀,可阻止 Agent 在執行期間污染自己的記憶。代價是完全沒有記憶。仍未解決的是,如何讓可寫入的記憶不會把注入內容帶到下一個工作階段。
數據流政策。禁止在同一工作階段使用不可信來源工具和高權限工具。已有公開的設計和參考程式碼,但目前沒有任何已推出的程式編碼 Agent 實施這項政策。
從上述放大因素可得出一點,適用於以上所有控制措施。Agent 採取行動的速度比人類審核快,因此在操作完成後才執行的控制措施只是記錄,不是控制。政策必須在呼叫工具之前生效。
最佳做法:六項必須遵守的原則
任何 Agent 在真實系統上執行前,都必須先落實以下六項控制措施:
- 在沙盒中執行 Agent。掛載專案目錄,而非主目錄。
- 提供只適用於該任務的憑證。透過代理伺服器或憑證代理,確保 Agent 無法取得其他憑證。
- 將 Agent 的設定存放在 Agent 無法寫入的位置。受管理的設定具有優先權;儲存庫中的任何內容都不能覆寫這些設定。
- 記錄每次工具呼叫及每條對外連線,並將記錄傳送至 SIEM。
- 首次執行前掃描工作區中的機密資料,並在工作區變更時再次掃描。
- 預設拒絕。只在寫入、傳送、刪除及支出時提示。
這些措施都無法防止提示詞注入。它們只能限制遭劫持的 Agent 能接觸到的範圍,而這是目前唯一由你掌控的部分。
常見問題
甚麼是 AI Agent 安全?
Agent 涉及三個攻擊面:其執行所在的主機、其使用的身分,以及決定其行為的上下文。作業系統及身分控制措施涵蓋前兩者;防護機制可識別已知的注入模式,但目前仍沒有任何措施能阻止檔案或網頁指示 Agent 該做甚麼。
AI Agent 安全的主要威脅有哪些?
模型本身、提示詞注入、工具及技能中毒、記憶中毒,以及審批疲勞。其後果包括破壞、資料外洩、橫向移動、持續潛伏及機密資料洩漏,與以往相同,但速度和規模已超出現有審查及偵測流程的設計能力。
如何保護 AI Agent 憑證?
將憑證限定用於該任務,並避免將任何其他憑證存到磁碟上。在首次執行前,使用 ggshield 掃描工作區中的機密資料,然後註冊 AI Hooks,讓提示詞、檔案讀取內容或 shell 命令中的機密資料,在傳送至模型前遭到封鎖。
來源:DEV Community · dev.to



