Skip to content

ADR-0004:安全管控插件层的定位——进程内策略执行层,不是安全边界 ​

  • 状态:已采纳
  • 日期:2026-09-15
  • 决策者:毕设作者
  • 相关文档:docs/02-安全管控插件层设计.md、docs/adr/0002-mcp-gateway-as-sole-egress.md、docs/adr/0003-openclaw-as-agent-core.md

背景 ​

本课题的主要实现部分是"安全管控插件层"。一个必须提前回答、且答辩时几乎必被追问的问题是:

这一层到底是不是安全边界?如果是,它能防住什么?

OpenClaw 官方文档给出了明确答案:插件与 Gateway 在同一进程中运行,应被视为可信代码;同时 OpenClaw 的整体信任模型是"单用户个人助理",明确不把同一 Gateway 内的多个用户视为互相敌对的租户。

如果我们把"防止 Agent 越权"的全部责任压在这一层上,就是在一个框架明确声明"我不做多租户隔离"的地方宣称自己做了隔离——这在答辩上是站不住的。

决策 ​

明确区分两个层次,并在所有文档中保持一致措辞:

层名称部署形态性质能防住什么
L1安全管控插件层OpenClaw 进程内的原生插件策略执行层(policy enforcement,非硬边界)拦截工具调用、参数校验与改写、字段脱敏、审计上报、行为约束与配额、提示词塑形
L2MCP 安全网关独立进程,独立凭证,独立部署单元安全边界(hard boundary)Agent 无凭证 ⇒ 物理上不可达;字段白名单裁剪;策略判定;审计落库

纵深防御的表述方式:L1 让"不合规的调用在发起前就被拦下",L2 让"即使 L1 被绕过,Agent 也拿不到它不该拿的数据"。

同时明确 L1 不承诺以下能力(写进文档、答辩时主动说明):

  • 不承诺抵御恶意插件代码(同进程 ⇒ 恶意插件可绕过钩子直接调用内部 API);
  • 不承诺多用户之间的隔离(框架不支持);
  • 不承诺在 Agent 进程被完全攻陷时仍有效(进程内策略层随宿主一起失守)。

理由 ​

  1. 诚实的技术论证比夸大更得分。答辩评委常见追问是"你这一层能不能被绕过"。主动区分硬边界与策略层,并给出绕过路径与兜底手段,比声称"绝对安全"更有说服力。
  2. 两层职责互补,不重复。L1 的优势是上下文完整——它能看到完整的会话、模型提示词、工具参数与 Skill 调用链,因此能做"语义级"判定(例如"这次调用与当前任务无关")。L2 的优势是权限最小——它拿不到会话上下文,但持有唯一的数据凭证。两者不可互相替代。
  3. 符合纵深防御(defense in depth)的常规做法。工业系统里"进程内策略 + 进程外网关"是标准组合,不是本课题的发明。

备选方案与拒绝理由 ​

方案为什么没选
只做 L1(插件层),不建独立网关插件层无法提供凭证隔离,"Agent 拿不到业务库账号"这一最强论证不成立;也无法做字段级裁剪。
只做 L2(网关),不做插件层网关看不到会话上下文,无法判断"调用是否与当前任务相关";也无法在提示词层面塑形、无法对 Skill 调用做配额约束。而且课题要求的"主要实现部分"就没了。
把 L1 做成独立代理进程(拦在 Agent 与网关之间)逻辑上更干净,但会引入第三个网络跳转与新的单点,且"插件层"的课题表述落空。原型阶段不值得。

后果 ​

正面

  • 安全论证分为"策略层拦住了什么"与"边界层兜住了什么"两条独立证据链,答辩时可用两组实验分别演示。
  • 与 OpenClaw 官方信任模型不冲突,不会被评委用官方文档反驳。
  • 插件层的定位清晰后,实现范围收敛:只做"钩子拦截 + 策略引擎 + 审计上报",不试图做凭证管理。

负面 / 代价

  • 需要额外实现并守护一个独立网关进程(PM2 配置、健康检查、降级策略)。
  • 文档与答辩材料中必须反复强调两者的区别,否则容易被误解为"两层做同一件事"。

相关设计约束 ​

  • L1 的所有策略判定结果都必须上报网关并落审计,不允许只在插件内留日志。审计的唯一权威落点是 business-db.audit_log。
  • L1 的策略失败必须 fail-closed(拒绝调用),不允许 fail-open。
  • L1 不得持有 business-db 或 ai-db 的任何连接串——它只调用网关的 HTTP/MCP 接口。