面向 agentic LLM 的通用執行期縱深防禦框架 · 案例:對抗「看似無害」的 agent-skill 攻擊
Kuan-Ju Chen(陳冠儒)· Po-Wen Chi(紀博文)
Graduate Institute of AI Interdisciplinary Applied Technology / Dept. of CSIE · National Taiwan Normal University
本簡報 = 整篇論文的逐節導讀(含 Related Work 與所有實驗細節)+ 現場可互動 Demo。
→ 用 方向鍵 移動;標有 LIVE DEMO 的頁面可直接點擊操作真實推論。
Part A — 問題
Part B — AgentGuard-DiD 設計
Part C — 攻擊語料(實證威脅)
Part D — 評估
Part E — 討論 / 誠實的負面結果 / 結論
Tool-using LLM agent 已能讀寫檔案、執行 shell、開網路連線;並可在執行期安裝第三方 skill 來獲得新能力。
skill=一個小套件:一份自然語言指示檔 + 輔助腳本。Agent 把它載入 context,任務需要時就執行。
這正是現代 agent 好用的原因——也是它危險的原因:
每安裝一個 skill,它就加入 agent 的執行鏈,繼承 agent 對檔案系統、shell、網路的完整能力。單一惡意/被污染的 skill 即可為所欲為。
攻擊面的本質變化
Duan et al., SkillAttack(arXiv:2604.04989);Supply-chain for Agentic Skills(arXiv:2603.00195)
本研究的標的 OpenClaw:不附任何外部輸入/輸出過濾器、也沒有 policy engine。惡意 skill 與主機之間,唯一的阻擋就是——base model 的對齊(模型自己學到要拒絕它判定有害的請求)。
對齊是真實且有價值的一道防線
在我們的量測中,它確實拒絕了大多數明目張膽的攻擊(後面數據:bare agent 攻擊成功率僅 12.8%)。
但「安全的模型 ≠ 安全的 agent」 (arXiv:2604.01438)
一旦把請求拆解成各自無害的步驟,或把惡意移位到已安裝的 skill 裡,模型的拒絕反射就不會被觸發——即使整體行為有害。
本論文的核心=在真實 agent 上直接展示這個失效模式,並設計一套「假設 base model 遲早會被騙、被騙時能把傷害擋住」的防禦。
使用者請求很平常(scaffold 專案 / 整理日曆 / 完成報表);skill 也宣稱是平常的工具。prompt 與 skill 各自都沒有 prompt-injection 過濾器要找的訊號——沒有「ignore previous instructions」、沒有嵌入程式碼、沒有外洩字串。傷害只活在「組合」與「執行的效果」裡:
→ 下一頁就是進入 agent 前的 L1 防火牆:可現場點擊,看它擋下明目張膽攻擊、卻放行看似無害的請求。
先點「⚠ 明目張膽」→ 被擋;再點「😇 看似無害」→ 放行(這正是結構性盲點)。也可自行輸入任何 prompt。
我們把工作放在六條研究線上對照。除非特別說明,引用他人的數字都是各作者在自己的資料集/威脅模型上報告的,不能與本文直接比較。
→ 接下來四頁逐條展開。
→ 我們研究的看似無害 skill 攻擊,就是這個家族在 agent-skill 上的實例:拆解發生在 prompt 與 skill 之間。
→ 這些工作建立了「攻擊面」;AgentGuard-DiD 貢獻的是「執行期的圍堵(containment)」。
把分類器/policy 放在輸入輸出邊界:Llama Guard(在安全分類法上微調 LLM)等。兩種失效反覆出現,直接塑造了我們的設計:
全部都在「不讓模型被騙」;AgentGuard-DiD 與它們互補——我們觀察「被騙之後 agent 做了什麼」。
AgentDojo / InjecAgent / ToolEmu 在間接工具輸出注入下評估 agent,對強模型一致量到兩位數攻擊成功率;CommandSans 消毒工具輸入來降低它。這些聚焦「工具觀測」的間接注入,但只在 prompt/tool 邊界評估、不看主機 syscall——正是我們下層要補的洞。
IsolateGPT 隔離 app 執行、Progent 在 tool-call 層強制最小權限。差別在觀察層級:它們仲裁 agent 宣稱的 tool call;我們的 L2/L3 觀察實際的 syscall 流,不論介面上怎麼描述。
下層承襲 HIDS 血緣:Forrest「短 syscall 序列=self 簽章」→ ADFA-LD / LID-DS → 18,966-trace DongTing。我們按 agent-turn 重用、用參數感知簽章,並首度加入「讓 LLM 讀 trace」、eBPF 汙點、資料溯源。
Zheng et al. 推廣用強模型評估其他模型的輸入輸出。AgentGuard-DiD 在三個點套用(判 prompt、判執行 transcript、判原始 syscall trace),並且罕見地量化「換裁判模型影響多大」——包含「用攻擊者同族模型當裁判」的陷阱。
沒有單一視角能完整看見一個看似無害的 skill 攻擊 → 防禦必須在執行路徑上的多個點觀察 agent,並把各點所見聯集起來。
請求+將呼叫的 skill 文字先做靜態篩查(L1);通過後,agent turn 在沙箱執行,L2 分析它實際做了/產出了什麼,L3 在 OS 與資料邊界盯著看。任一層觸發即判惡意;每層都刻意設計成高精準度,故聯集能提升召回而不堆高誤報。
在文字邊界套 zero-shot LLM judge:一次判使用者 prompt、一次判要載入的 skill 文字。回傳精簡裁決(malicious/benign+類別+簡短理由),可解釋且不會被藏在文字裡的指令挾持。
為何刻意用 zero-shot 而非訓練分類器?訓練型不是過度封鎖含觸發詞的良性輸入,就是記住來源特徵、遇未見分佈就崩(§L1 泛化會重現)。
抗規避前處理:Unicode NFKC 正規化、去零寬/組合字元、收合單字元間距;base64 解碼後再判一次;另加確定性高精準匹配器抓明目張膽的覆寫/注意力挾持框架。
L1 的結構性極限:判 prompt 抓「操縱在請求裡」的攻擊;判 skill 抓「payload 在程式碼裡」的攻擊。兩者都看不見看似無害攻擊——這就是後兩層存在的理由。
右側即 L1 即時推論。試「看似無害」那組 → L1 放行 → 接著看 L2/L3。 LIVE
請求一旦被放行,agent 執行任務時就暴露了行為。L2 判「它做了什麼」而非「它被要求做什麼」。兩個方法:
差別關鍵:一行指令可能看來例行(python3 setup.py),但它寫出的檔案含寫死的 admin 憑證;一個日曆編輯指令看來普通,效果卻是刪光所有事件。藉由判效果,這一層正好救回 prompt/skill 文字所隱藏的那類危害。
兩個方法都以「安全稽核員」角色 prompt,且刻意不告訴它攻擊目標——所以正向判定反映的是「觀察到有害動作」,而非「事先知道這是攻擊」。
在語言層底下觀察這一輪,三個互補方法:
strace 追蹤,套參數感知行為簽章:讀憑證/機密檔(.ssh、.aws/credentials、.env、/etc/shadow)、環境變數外洩、download-and-execute、reverse-shell;再加一個無詞彙表行為特徵的學習分類器。承襲 HIDS 但按 agent-turn、看參數而非只看名稱。openat 與 connect,只有當同一程序讀了憑證檔後又對外連線才告警——「讀→外洩」的因果,是單看 read 或單看 connect 都分不出的。核心級開銷,可常駐生產。L3 就是把 base model「遲早會被騙」時的傷害,在 kernel 與磁碟資料這一層擋下來。
turn 裁決=三層六方法的聯集。偵測器總會出錯,故被擋的 prompt 提供對話內覆寫(明確風險確認後以繞過防火牆重送),每次 block 與 override 都寫入每使用者稽核日誌。
讓 LLM 方法在規模下可負擔:L1 以階梯運作——確定性框架匹配器零模型成本秒拒明顯攻擊;快模型篩其餘;只有帶風險訊號(URL、編碼 blob、覆寫語氣)才問強模型。
三個免模型方法(簽章、eBPF、溯源)構成確定性層,可在預算/離線/氣隙環境獨立運作,LLM 方法則作為可選的召回增強。
評估防禦之前,得先實證兩件事:(a) 單靠對齊,看似無害攻擊會過關;(b) prompt-and-skill 防火牆看不見它們。
SkillAttack 五階段迴圈(攻擊路徑跨回合精修,而非單發固定):
分析 skill 攻擊面 → 生成對抗 prompt → 在沙箱對目標 agent 執行 → 從產物判定是否成功 → 精修 ↺
171-skill 基準= Hot100(100 個最多人安裝的真實社群 skill)+ 71 個 SkillInject 對抗 skill(把惡意藏在普通描述後)。
關鍵實驗控制:攻擊中的 agent、攻擊者、成功裁判都用同一個開源模型 qwen3.5-122b-a10b → 量的是 agent 的內在抵抗力(無任何外部防禦)。AgentGuard-DiD 另外在 §評估獨立測。
忠實復現原 pipeline,只修一個執行預算誤設(否則 agent 會在攻擊開跑前就因 prompt 過長而拒絕)。
「對齊是唯一、且不足的防禦」:成功=產物顯示危害實現;否則標為 ignore(agent 拒絕或做了防禦/補救)。多數嘗試以 ignore 收場——這正是對齊在做事;但殘留的那些,就是本文主題。
在對抗性 SkillInject skill 上:
在真實 Hot100 skill 上(多數 skill 根本沒可利用面):skill 層 16% 被攻陷、分析器導出的個別攻擊面 38.5% 被攻陷。
→ 在獨立跑的目標上,重現原作核心定性發現:是「攻擊路徑精修」讓 agent-skill 攻擊變得有效,也確立「相當比例的攻擊能擊敗對齊」。
把兩組 skill 的成功攻擊匯集=66 個,全評估通用。每個都是「OpenClaw 對齊沒擋住」的攻擊。用兩套互補分類法看它:
兩欄的落差本身就是發現:DoS 與釣魚的 skill 確實攻陷 agent,卻從不經由其名義向量(資源耗盡迴圈、誘騙外寄信被對齊幾乎全拒),而是走它同時暴露的另一個面(寫死憑證、未授權上傳)→ 被歸為後門或外洩。對齊是「選擇性有效」的。
把 66 個成功攻擊各自用強 zero-shot judge 獨立篩:一次判 prompt、一次判 skill 文字。
兩者聯集仍漏掉相當比例。讀 judge 自己給漏抓的理由最有啟發:
外洩 SSH 金鑰的試算表 skill →「ordinary task request to create a financial spreadsheet」
刪光事件的日曆 skill →「ordinary calendar management, no override or exfiltration attempt」
judge 沒判錯——文字真的無害。惡意不在任一元件,而在它們的組合、以及執行的效果。這就是「prompt 防火牆必要但不充分」的結構性原因。
把 6 個偵測方法各自在 66 攻擊上打分。最強的單一方法不在 L1,而在 L2:判執行效果 63.6%,險勝 prompt 防火牆 62.1%,遠勝 skill/指令判斷。
層內聯集:靜態層 72.7%、執行語意層 68.2%、執行期層 24.2%;全套 84.8%。
| 層 | 方法 | 偵測 |
|---|---|---|
| L1 | prompt 防火牆 | 62.1% |
| L1 | skill 文字防火牆 | 36.4% |
| L2 | 指令判斷 | 36.4% |
| L2 | 執行效果判斷 | 63.6% |
| L3 | syscall 偵測 | 21.2% |
| L3 | 資料溯源 | 3.0% |
| 全套六方法 | 84.8% | |
點一個例子 → 各層真的即時推論(L1/L2 呼叫 LLM judge、L3 跑訓練好的 syscall 模型+資料溯源),顯示哪層攔下。旗艦例 python default_password:L1 全放行 → L2 效果層抓到寫死的後門。
逐方法/逐層的比率會低估深層的價值(語料裡很多攻擊的惡意程式碼靜態層本就讀得到)。更銳利的問法是組合式的:在全部 2⁶−1 個非空子集裡,哪些能到天花板、用幾個方法?
答案=最強的縱深防禦證據:84.8% 不只全套能到,一個「每層各取一法」的三方法組合(prompt+效果+溯源)也能到;而任何單層、任何兩層配對都到不了。
最小基數的最佳解=每層一法,且去掉任一層天花板就下降 → 三層互補、缺一不可。
| 組合 | 偵測 | 組合 | 偵測 |
|---|---|---|---|
| L1 only | 72.7% | L1+L2 | 83.3% |
| L2 only | 68.2% | L1+L3 | 75.8% |
| L3 only | 24.2% | L2+L3 | 71.2% |
| L1+L2+L3 | 84.8% | ||
18 個擊敗 prompt+skill 防火牆的攻擊裡:
這就是整個設計的重點:深層不是「重複確認防火牆已標記的東西」,而是唯一看得見看似無害攻擊的方法。
18 個裡有 10 個仍被所有方法漏掉 → 下面專門刻畫這個「殘餘」與部分解方。
四個 LLM 方法的好壞取決於裁判模型。用「驅動 agent 的同一個開源模型」當裁判是最糟的選擇。
強專有裁判(Claude)在 4 個方法中的 3 個勝出,尤其執行效果判斷 63.6% vs 16.7%(推理「產物之危害」最吃模型能力);攻擊者同族模型只在原始指令判斷略勝。
聚合:四方法聯集 83.3% → 63.6%;全套(含免模型的執行期方法)84.8% → 71.2%。
兩個部署教訓:① 守門能力是第一級設計參數,不是實作細節;② 別用攻擊者同族模型當裁判。
訓練型記住了「來源特徵」;zero-shot 沒訓練過任何一個,反而能轉移。——正是 guardrail 文獻報告的過度防禦與不泛化,在我們自己的 baseline 上重現。
執行期層最能緩解「任何 skill 語料都太小」的疑慮——syscall 偵測可在大型公開資料上評估。三個結果:
→ 下一頁的 Demo「L3 syscall 模型」卡片即時載入這個模型的訓練資訊,並對每條 trace 即時推論。
底部「L3 syscall 模型」卡片顯示訓練語料、GroupKFold F1、vs 手寫簽章;點任一例子按「執行推論」,模型會對真實 trace 即時給出 model_prob 與觸發簽章。
這兩個方法都不用模型,構成可離線常駐的確定性防線。
66 個裡有 10 個躲過所有方法。值得說清楚為什麼,因為誠實的答案界定了這些防禦的能力上限:
這些攻擊的危害純屬內容/資料語意:只在特定情境才惡意的寫死值、微妙偏誤的簡報、只在資源用量上異於平常工作的 DoS。
我們試了一個整體 judge(同時給它 skill+prompt+指令+輸出,要它推理整條鏈,期望看出「宣稱用途 vs 行為」的矛盾):結果全數失手,還在良性對照上誤報一半——因為 skill 本就設計成惡意、agent 忠實執行,沒有「行為 vs 用途」的矛盾可找,危害留在 transcript 不暴露的值裡。
更多 LLM 判斷幫不上忙——訊號不在語意裡。
唯一能救回部分殘餘的是資料溯源,正因為它放棄意圖、直接比對前後的真實資料。
最難的(主觀偏誤、以「最佳化」為名關掉安全檢查)看來需要領域政策或人工審查——我們不宣稱解決。
為直接量測「相對於已對齊 base model 的邊際價值」:跨來源抽 172 攻擊+60 良性,分別以 裸 agent 與 加 AgentGuard-DiD 執行,從產物評真實攻擊成功。
誤攔良性 0;McNemar p=0.0009 顯著;且防禦從未放行任何裸 agent 已拒絕的攻擊。降幅集中在真正攻陷裸 agent 的來源(人工競賽攻擊、in-the-wild jailbreak)。
更大的1,678 prompt 逐類研究把誤攔壓到 0.2%(六個良性任務家族)→ 高精準層的聯集保住良性效用。
務實形狀:六方法中三個免模型(簽章、eBPF、溯源)→ 可零成本跑確定性層,LLM 方法只在預算/延遲允許時加上。對商用硬體或氣隙部署,這分層是「可部署」與「負擔不起」的差別。
cat│curl)的外洩。對「會安裝第三方 skill 並在主機上行動」的 agent,已對齊的 base model 是必要但不完整的防禦。看似無害的 skill 攻擊——prompt 與 skill 各自都像普通工作、危害只活在執行效果——夠頻繁地擊敗對齊,且結構性地擊敗 prompt-and-skill 防火牆。
AgentGuard-DiD 以縱深防禦回應:靜態防火牆 + 判「做了/產出了什麼」的執行語意層 + 盯 syscall、於核心關聯「讀憑證→外洩」、比對前後資料的執行期層。
在擊敗對齊的攻擊上,全套抓下七分之六(84.8%);深層精準救回防火牆看不見的攻擊;最小最佳組合=每層各一法——層與層互補的直接證據。我們也證明防禦強烈依賴守門模型能力、攻擊者同族模型是錯的選擇、純資料語意殘餘要靠真實溯源而非更多模型判斷。
主張:效果級與執行期監控,應成為「會在主機上行動的 agent」之 prompt guardrail 的標準搭配。程式碼、資料清單、模型、互動儀表板全數釋出。
AgentGuard-DiD: Defense-in-Depth Against Benign-Looking Agent-Skill Attacks
現場可操作:
Kuan-Ju Chen · Po-Wen Chi · National Taiwan Normal University · 2026