护栏:输入/输出过滤、沙箱与作用域收缩。
"加上护栏"是智能体安全中被过度承诺的一句话。护栏是真实且必要的,但前提是你清楚哪一类做哪件事、哪些会失败时趋开放。本文区分四个护栏家族——输入、输出、执行沙箱、能力作用域——并展示如何分层,让弱的覆盖强的留下的缝隙。
一个能防止一厢情愿的分类法
大多数对护栏的失望源自类别混淆:团队部署了一个内容分类器(概率性检测器),却期望它表现得像沙箱(硬边界)。它们是失败模式不同的不同工具。
- 概率性护栏——输入/输出分类器、基于 LLM 的裁判。它们估计"这是不是坏的?"它们失败时趋开放:绕过模型的攻击者会无声地通过。
- 确定性护栏——schema 校验、白名单、沙箱、能力作用域。它们强制"这在结构上不被允许"。它们失败时趋关闭:即便面对新颖攻击,被禁动作也不会发生。
设计规则:把你的信任放在确定性护栏上,把你的可见性放在概率性护栏上。分类器是烟雾报警器,不是防火门。请造那扇防火门。
输入护栏
输入护栏在内容到达模型之前检查它:用户消息、检索片段、工具结果。它们能做的有用工作:
- 检测并标记已知注入模式与越狱形态(抬高攻击者成本、收集信号)。
- 剥离或中和结构上危险的内容:HTML 注释、隐藏 Unicode、零宽字符、检索文本中的嵌入标记。
- 强制硬性输入限制:长度、允许的语言/编码、结构化输入的 schema、检索的来源白名单。
- 标注来源:把每个片段标记为可信(运营者)或不可信(检索/工具),以便下游层区别对待。
确定性部分(剥离隐藏标记、强制 schema、来源标注)是持久的。分类器部分是尽力而为。不要让"我们有输入过滤器"代替下面的结构性控制。
输出护栏
输出护栏在任何东西据其行动之前检查模型产出。共有两种截然不同的类型,对智能体而言第二种重要得多。
内容输出检查
扫描生成文本中是否有泄露的密钥、PII、被禁内容或外泄标记(例如编码了上下文的外部图片 URL)。在响应到达用户或渲染器之前剥离或拦截。
动作输出检查(关键的那个)
在任何工具调用执行前,确定性地校验它:此状态下该工具是否被允许?参数是否匹配严格 schema?目的地是否在白名单上?操作是否在速率/数量限制内?这里是你阻止智能体据一次成功注入行动之处,且它绝不能实现为另一个同一攻击者提示能绕过的 LLM。
# Action guardrail: deterministic check before execution def allow_tool_call(call, state): if call.name not in state.allowed_tools: return deny("tool not permitted in this state") if not schema_valid(call.name, call.args): return deny("argument schema violation") if call.name == "send" and call.args.to not in state.allowlist: return deny("destination not allowlisted") return allow()
执行沙箱
有些智能体会运行代码或 shell 命令。对这些,护栏不是对命令字符串的分类器——而是命令运行所处的环境。假定命令是敌对的,并把箱子设计成能容纳一个敌对命令。
- 隔离:每任务一个一次性容器/微虚机,无宿主挂载,丢弃特权,用后即杀。
- 出站默认拒绝:沙箱无法触及任意主机;出站为白名单或不存在。即便代码执行得手,这也能中和大多数外泄。
- 资源上限:CPU、内存、墙钟时间和磁盘限制,以遏制资源滥用与失控循环。
- 无环境凭据:沙箱默认不持有密钥或云元数据访问;能力按任务、窄范围注入。
沙箱保护宿主。它不保护你刻意交进沙箱的数据,也不阻止智能体在其内部合法调用的工具被滥用。沙箱是必要的,不是充分的——要与能力作用域配套。
能力作用域——能涵盖其余的那道护栏
最有效的护栏是你从未使其成为可能的那个动作。能力作用域意味着每个智能体(及每个子智能体)只被授予其任务所需的工具、数据作用域和凭据,别无其他——在边界处强制,而非在提示中请求。
- 按任务、限时、窄作用域的凭据,而非长期宽泛的凭据。
- 参数化且结果受限的读取工具,而非通用查询接口。
- 信任分离:用一个无工具的读取器读不可信内容;一个从不摄入原始不可信文本的特权执行者。
- 状态机:工具仅在其有效的状态可用,使被注入的指令无法召唤一个不合时宜的能力。
作为概率性外层,可以——一个独立的裁判模型能捕捉一些失败并增加信号。作为决定破坏性工具是否运行的那个控制,不行:它与被它裁判的智能体共享提示词注入失败模式,能骗过其一的载荷可被构造成同时骗过两者。执行高影响动作的决定,必须落在确定性代码上——schema、白名单、状态——而非第二个模型的意见。
你不应去尝试枚举。输入受结构约束处,输入护栏应呈白名单形态(强制 schema、来源列表、编码);输入是自由文本处,应呈尽力检测形态(标记、记录、抬高成本)。承认自由文本分类器会漏,并把系统设计成漏了也能存活——这种存活力来自确定性的内层,而非一个完美过滤器。