Lab-confirmed:本文 reference 實作來自我(Maki)自家在跑的個人 PKI(mk-brain / ERIKA Bot / Inbox Bot 等),不是 enterprise production case study。Code snippet 為 reference 設計,非實際在跑的版本。
你以為對話結束了,污染卻還留在裡面
很多人把 context 想成一個會自己蒸發的東西。
這一輪對話結束,視窗清空,模型就重來。
但只要你的 agent 背後接了 memory、vector store、長期筆記、RAG cache,情況就完全不同。
你不是在管理一段 prompt。
你是在管理一個會累積、被重複引用、還可能跨 session 存活的脈絡層。
ZombieAgent 讓很多人第一次真正意識到這件事。
研究者展示的不是單次 jailbreak 多精彩。
而是污染一旦種進 memory 或 retrieval layer,下一次 query 依然可能把它撈回來。
也就是說,對話可以結束,攻擊不會自動結束。
這對 builder 很麻煩,因為多數團隊對 context 的治理幾乎只有「看起來能用」。
很少有人替 namespace 種 canary。
很少有人替記憶寫入做 ACL。
更少有人規定:LLM 自己生成的內容不能直接升格成之後的依據。
所以真正危險的,不是 agent 某一天突然講錯一句話。
而是它已經連續半年在錯的脈絡上繼續推理,團隊還以為那叫 personalization。
Context boundary 的工作,就是把這條「一次失誤變成長期污染」的路先截斷。
Context Boundary:上下文能留多久、污染多遠
當 memory 和 context layer 變成持久層,偵測就不能只靠人盯 dashboard。
Case:
主:ZombieAgent attack technique(2026-01 LinkedIn 安全社群揭露)——研究者展示 AI agent 透過 memory / context layer 的持續資料洩漏(persistent data leakage)。即使對話結束、session 結束、agent 重啟,毒已經種在 vector store 裡,下一次 query 仍會被污染。
次:你的 RAG 知識庫被污染半年——完全不知道。沒人 audit、沒 alert、沒監控。直到客戶投訴「你的 AI 客服說了奇怪的事」才發現。這是 zh-TW 工程社群最常 vent 的 sentiment:「公司搞 RAG 但完全沒人在意 source 可信度」。
核心問題:怎麼deterministic 早期偵測而不靠盯 dashboard?
Rule:Canary Tokens(中文我建議叫「哨兵令牌」)。在你的記憶體 / RAG 庫塞一個「絕對不該出現在 LLM output」的隨機字串,例如 MK_CANARY_<random>。output 偵測到 canary echo → fail-closed + log。
這裡的關鍵不是多做觀測,而是讓污染第一次外露時就留下可機器判斷的訊號。
| Threat | Mitigation | Validated in (reference) |
|---|---|---|
| RAG / memory 污染半年沒人發現 | 每 namespace 至少 1 個 canary entry;output redaction layer 偵測;fail-closed + weekly digest(不做 daily dashboard,反 L4) | memory-hall + mk-brain |
| Memory & Context Poisoning(ASI06) | 寫入 path 加 HMAC signature;讀取 path 加 ACL;「LLM 自己想寫」這條路徑 deny by default | memory-hall write hygiene |
| Misinformation(LLM09)放大 | 引用必須 trace 到 raw_source tier;llm_derived 不得當「事實」呈現 | mk-brain Observatory layer |
Reference 實作(示意非 production code,依你環境調整):
# Canary tokens — deterministic 早警,不靠盯 dashboard
import secrets
CANARY_PREFIX = "MK_CANARY_"
def plant_canary(namespace: str) -> str:
"""每個 RAG namespace 至少種一顆 canary"""
canary = f"{CANARY_PREFIX}{secrets.token_hex(8)}"
db.insert(MemoryEntry(
content=f"Canary marker: {canary}",
source_tier="canary", # 不會被 RAG 正常 surface
upstream_ids=[],
provenance_hash=hmac_sign(canary),
))
return canary
def detect_canary_leak(llm_output: str, known_canaries: list[str]):
"""LLM output 偵測到 canary echo → fail-closed"""
for canary in known_canaries:
if canary in llm_output:
log_incident(f"CANARY LEAK detected: {canary}")
raise SecurityError("RAG 被污染或 LLM exfil canary")
對應 OWASP:這篇先看哪幾條
ASI06 Memory & Context Poisoning:這篇處理的核心就是污染如何從單次上下文擴散成持久狀態。LLM08:2025 Vector and Embedding Weaknesses:當持久 context 依賴向量檢索,檢索層就是污染傳播器。LLM09:2025 Misinformation:context 被污染之後,模型輸出的錯誤會以看似有根據的形式持續放大。
想動手做? 這篇文的概念有對應的 5 課完整課程: 脈絡邊界 101 →
也可以接著看下一個邊界:攻擊面邊界