Agent 工具执行安全框架:企业级 Agent 的"最后一公里"

Agent 工具执行安全框架

控制 Agent 的"手"------工具执行层安全的通用架构设计。与 Agent 引擎无关,可被任何 Agent 项目参考复用。


一、定位

行业已有成熟的大模型统一网关方案,控制 Agent 的"脑"------模型访问、Token 限流、Prompt 安全、输出审核、成本管控。

但 Agent 不只是聊天。Agent 的本质是通过工具与真实系统交互。网关管不了 Agent 读了哪个文件、跑了什么命令、访问了哪台内部服务。

本框架补上这块:控制 Agent 的"手"------工具执行层

arduino 复制代码
┌─────────────────────┐         ┌─────────────────────┐
│   LLM 统一网关 (已有) │         │  工具执行安全层 (本框架) │
│   控制"脑"           │         │  控制"手"             │
│                     │         │                     │
│ • 模型访问控制        │         │ • 数据安全            │
│ • Token / 限流       │  ←───→  │ • 操作安全            │
│ • Prompt 注入防护     │         │ • 系统安全            │
│ • 输出内容审核        │         │ • 网络安全            │
│ • 成本管控           │         │ • 权限安全            │
│                     │         │ • 合规审计            │
└─────────────────────┘         └─────────────────────┘
              两层合在一起 = 企业级 Agent 安全闭环

网关管住 用户 ↔ LLM 的对话通道(输入过滤 + 输出审核)。 本框架管住 LLM ↔ 真实世界 的操作通道(工具输入拦截 + 结果输出扫描)。

威胁模型

威胁类别 攻击场景
数据泄露 Agent 通过 read_file 读到 API Key、私钥、PII,数据进入 LLM 上下文后不可控
破坏性操作 Agent 执行 rm -rf /、覆写系统配置、注入恶意依赖
资源耗尽 fork bomb、死循环、大量内存分配,导致宿主机不可用
网络逃逸 Agent 通过 exec(curl ...)web_fetch 访问内部服务或向外泄露数据
权限提升 Agent 通过 spawn 创建不受控子 Agent,通过 cron 持久化任务
供应链攻击 恶意 Skills/插件被安装后获得工具执行权限

二、核心设计原则

原则 1:唯一咽喉(Single Chokepoint)

无论什么 Agent 引擎,所有工具调用最终都经过一个出口。拦住这个出口 = 控制 Agent 的全部真实操作能力。

scss 复制代码
agent_loop()
  → tool_registry.execute(name, params)   ← 唯一咽喉
    → tool.validate(params)
    → tool.run(**params)

主 Agent、子 Agent(spawn)、MCP 工具全部经过此入口。在类/trait 级别替换一次,所有实例自动生效。

原则 2:三阶段流水线(Before / Around / After)

makefile 复制代码
Before: 策略检查 + 插件钩子(是否允许执行)
Around: 选择执行环境(宿主机 / 容器)+ 实际执行
After:  DLP 扫描 + 审计记录

三个阶段的输入输出严格定义,每个阶段可独立启用/禁用。

原则 3:零侵入(Runtime Weaving)

不 fork、不改 Agent 引擎源码,运行时注入。

  • Python: monkey-patch 类方法
  • Node.js: Proxy/Reflect 或原型链替换
  • Go: 接口适配器包装
  • Rust: trait 实现替换

为什么这很重要:改源码 = fork,fork = 维护负担,维护负担 = 跟不上上游演进。零侵入意味着 Agent 引擎可以源源不断地升级,安全层只管自己的事。

兼容性风险与缓解:Agent 引擎升级后,咽喉点的方法签名可能变化(参数增减、方法重命名),导致 monkey-patch 静默失效。缓解措施:

  • 启动时校验:安全层注入前检查目标方法是否存在、签名是否符合预期(参数名/参数数量)。校验失败时拒绝启动并告警,而非静默降级
  • 版本声明 :安全层配置中声明兼容的 Agent 引擎版本范围(如 engine_compat: "nanobot>=0.9,<2.0"
  • 降级策略:校验失败时可选行为------拒绝启动(安全优先)或跳过安全层并告警(可用性优先)

原则 4:双层沙箱(Transparent + Isolated)

执行环境和策略模式是两个正交维度,任意组合:

scss 复制代码
              ┌─────────────────────────────────────┐
              │       策略模式 (Policy Mode)          │
              │  monitor │ enforce │ disable          │
┌─────────────┼──────────┼─────────┼─────────────────┤
│ transparent │ 记录不拦  │ 违规拦截 │ 跳过安全层       │
│ (宿主机直执) │          │         │                 │
├─────────────┼──────────┼─────────┼─────────────────┤
│ restricted  │ 记录不拦  │ 违规拦截 │ 跳过安全层       │
│ (子进程+限制)│+资源隔离  │+资源隔离 │+资源隔离         │
├─────────────┼──────────┼─────────┼─────────────────┤
│ isolated    │ 记录不拦  │ 违规拦截 │ 跳过安全层       │
│ (容器)      │+物理隔离  │+物理隔离 │+物理隔离         │
└─────────────┴──────────┴─────────┴─────────────────┘
  执行环境轴                策略模式轴

执行环境决定在哪里跑 (宿主机 / 受限子进程 / 容器),策略模式决定怎么管 (只审计 / 阻断 / 不管)。两者独立配置,策略/钩子/DLP/审计在所有执行环境上同样生效

原则 5:策略与钩子分离

scss 复制代码
内置策略 (Policy):配置驱动的静态规则,受 mode 控制
  → enforce 模式下阻断,monitor 模式下仅记录

插件钩子 (Hooks):用户自定义的动态逻辑,始终权威
  → 无论 mode 为何值,钩子的 deny 一律阻止执行

为什么要分离 :用户安装了自定义安全插件(如交互式审批),当用户明确点击"拒绝"时,这个决策不应该被系统的 monitor 模式覆盖。用户的显式决策永远优先于系统默认行为。

原则 6:人机协作(Human-in-the-Loop)

Agent 在执行关键操作前,可以暂停等待人类确认。安全层提供异步审批通道,让人类在关键时刻介入决策,而 Agent 引擎本身不知道发生了什么------它只看到"工具执行慢了一点"。


三、三阶段流水线(核心架构)

yaml 复制代码
┌──────────────────────────────────────────────────┐
│       tool_registry.execute(name, params)          │
│                                                    │
│  ┌──────────────┐                                  │
│  │ Phase 1a     │ 内置策略检查(受 mode 控制)        │
│  │ Policy Gate  │ • 工具白/黑名单                   │
│  │              │ • 路径 ACL                        │
│  │              │ • 命令黑名单                       │
│  │              │ • 域名白名单                       │
│  │              │                                  │
│  │  monitor: 记录但不阻断                           │
│  │  enforce: 拒绝 → 返回 Error                     │
│  └──────────────┘                                  │
│  ┌──────────────┐                                  │
│  │ Phase 1b     │ 插件钩子(始终权威)                │
│  │ Plugin Hooks │ • 同步钩子: on_before(tool, params)│
│  │              │ • 异步钩子: on_before(tool, params, ctx)│
│  │              │ • 支持交互式审批                    │
│  │              │                                  │
│  │  deny → 一律阻止,不受 mode 影响                  │
│  │  allow → 继续执行                                │
│  └──────────────┘                                  │
│  ┌──────────────┐                                  │
│  │ Phase 2      │ 执行环境                          │
│  │ Around       │ • transparent: 宿主机直接执行      │
│  │              │ • restricted: 子进程+资源限制       │
│  │              │ • isolated: 容器内执行             │
│  └──────────────┘                                  │
│  ┌──────────────┐                                  │
│  │ Phase 3      │ 审计 + DLP                       │
│  │ After        │ • 结果敏感数据扫描                 │
│  │              │ • CRITICAL → 阻断                 │
│  │              │ • HIGH → 脱敏                     │
│  │              │ • 结构化日志 → SIEM               │
│  └──────────────┘                                  │
│         │                                          │
│         ▼ result 返回 LLM 上下文                     │
└──────────────────────────────────────────────────┘

三阶段数据流

阶段 输入 输出 可扩展点
Before (1a) tool_name, params, policy allowed / denied / monitored 策略文件热加载
Before (1b) tool_name, params, HookContext allowed / denied + reason + message 自定义插件
Around (2) tool_name, params, sandbox_mode result 或 exception 执行环境选择
After (3) result, DLP patterns processed_result, audit_record 自定义 DLP 模式、SIEM 对接

四、策略引擎规范

策略文件独立于代码,支持热加载:

json 复制代码
{
  "mode": "enforce",
  "dlp": {
    "enabled": true,
    "on_critical": "block",
    "on_high": "redact"
  },
  "tools": {
    "read_file": {
      "action": "allow",
      "denied_paths": ["**/.env", "**/.env.*", "**/credentials*", "**/*.pem", "~/.ssh/**"]
    },
    "write_file": {
      "action": "allow",
      "denied_paths": ["**/.git/**", "/etc/**", "/usr/**"]
    },
    "exec": {
      "action": "allow",
      "sandbox": "restricted",
      "denied_commands": [
        "^sudo\\b",
        "\\brm\\s+-rf\\s+/",
        "\\bcurl\\b.*\\|\\s*(bash|sh)",
        "\\bchmod\\s+777\\b",
        "\\bshutdown\\b",
        "\\breboot\\b"
      ],
      "max_timeout": 60
    },
    "web_fetch": {
      "action": "allow",
      "allowed_domains": ["*.github.com", "docs.python.org"],
      "denied_domains": ["*"]
    },
    "spawn": {
      "action": "allow",
      "max_concurrent": 3,
      "inherit_policy": true
    },
    "cron": {
      "action": "deny"
    }
  }
}

策略模式

模式 行为
enforce 违规时阻止执行,DLP 命中时阻断/脱敏
monitor 仅记录日志,不阻止任何调用(用于策略调优阶段)
disable 跳过安全层(不推荐用于生产)

策略层级与优先级

全局 mode 和工具级 action 的关系:

全局 mode 工具 action 最终行为
enforce allow + 规则通过 允许
enforce allow + 规则不通过 拒绝
enforce deny 拒绝
enforce monitor 允许 + 记录
monitor allow + 规则不通过 允许 + 记录违规
monitor deny 允许 + 记录违规
disable 任意 允许(跳过安全层)

简言之:

  • disable → 一切放行
  • monitor → 一切放行,但违规会被记录(用于策略调优阶段)
  • enforce → 按工具级规则执行

例外 :插件钩子的决策不受全局 mode 影响 。即使 mode: monitor,插件返回 deny 仍然阻止执行(见原则 5)。

策略规则字段

字段 适用工具 说明
action 所有 allow / deny / monitor
denied_paths read_file, write_file, edit_file glob 模式黑名单
allowed_paths read_file, write_file, edit_file glob 模式白名单
denied_commands exec 正则表达式黑名单
allowed_domains web_fetch 域名白名单
denied_domains web_fetch 域名黑名单
sandbox exec transparent / restricted
max_timeout exec 最大执行时间(秒)
inherit_policy spawn 子 Agent 是否继承父策略

五、插件系统规范

安全层通过约定的插件目录(如 ~/.your-agent/security-plugins/)加载用户自定义逻辑。

插件发现与加载

  • 目录扫描:*.py(Python)或其他语言的约定扩展名
  • 按文件名字母序加载,钩子按注册顺序执行
  • 第一个返回拒绝的 Before Hook 即终止执行链

Before Hook 接口

同步钩子(简单场景):

python 复制代码
def on_before(tool_name: str, params: dict) -> dict | None:
    """返回 None 表示放行,返回 dict 表示拦截。"""
    if tool_name == "exec" and "rm" in params.get("command", ""):
        return {
            "allowed": False,
            "reason": "Dangerous command detected",
            "message": "This command was blocked for safety reasons.",
        }
    return None

异步钩子(需要用户交互):

python 复制代码
async def on_before(tool_name: str, params: dict, ctx=None) -> dict | None:
    """异步钩子,通过 ctx.request_approval() 请求用户审批。"""
    if ctx is None:
        return None  # 无交互通道时默认放行

    decision = await ctx.request_approval(tool_name, params, summary="...")
    if decision.get("action") == "deny":
        return {
            "allowed": False,
            "reason": "User denied",
            "message": "User declined this operation. Ask what to do instead.",
        }
    return None

Hook 返回值规范

字段 类型 说明
allowed bool False 表示拦截
reason str 内部日志原因(出现在审计日志中)
message str(可选) Agent 侧可见的消息。插件通过此字段控制 AI 收到的拒绝理由。如未提供,使用默认文案

message 字段的设计意图:区分"用户主动拒绝"和"安全策略阻止"。当用户在 UI 上点击"取消"时,Agent 收到的应该是"用户不想执行这个操作",而不是"被安全策略阻止"------这影响 Agent 的后续行为。

After Hook 接口

python 复制代码
def on_after(record) -> None:
    """审计后置钩子,可对接外部 SIEM 系统。"""
    if record.dlp_findings:
        send_to_siem(record)

自定义 DLP 模式

python 复制代码
DLP_PATTERNS = {
    "INTERNAL_IP": [r"\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"],
    "COMPANY_SECRET": [r"(?i)PROJECT[-_]?CODENAME[-_]?\w+"],
}

关键设计决策:插件始终权威

内置策略受 mode 控制------monitor 模式下仅记录不阻断。但插件钩子的决策始终权威 ,不受 mode 影响。

这确保了:用户安装的自定义安全插件(如交互式审批)中,用户明确点击"拒绝"时,即使系统处于 monitor 模式,工具也会被阻止。


六、交互式审批通道

问题背景

许多场景下,Agent 在执行工具前需要人类确认------类似 Cursor 的 Run/Cancel 交互。安全层需要提供一种机制,让插件在工具执行前暂停并等待人类决策。

通道机制

scss 复制代码
插件 on_before()
  → ctx.request_approval(tool, params, summary)
      │
      │  异步 Future 创建,挂起等待
      │
  ┌───┴───┐
  │  双向   │  WebSocket / IPC / 或任何双向通信
  │  通信   │
  └───┬───┘
      ↓
  前端 UI 显示审批卡片
  [Run] [Allowlist] [Cancel]
      │
  ┌───┴───┐
  │  双向   │
  │  通信   │
  └───┬───┘
      ↓
  插件收到 decision
  {action: "allow_once" | "allowlist" | "deny"}

审批协议

请求(安全层 → 前端)

json 复制代码
{
  "type": "tool_approval",
  "id": "uuid-request-id",
  "tool": "exec",
  "params": {"command": "npm install express"},
  "summary": "npm install express"
}

响应(前端 → 安全层)

json 复制代码
{
  "type": "tool_approval_response",
  "id": "uuid-request-id",
  "action": "allow_once"
}

无超时设计

审批请求无限期挂起,直到:

  • 用户明确响应(Run / Allowlist / Cancel)
  • 连接断开(应用关闭、进程被杀等)→ 自动视为 deny

为什么不设超时:工具执行是关键操作。如果用户离开电脑去喝咖啡,回来后工具不应该因为超时而自动执行或自动拒绝。挂起是最安全的默认行为。

非交互场景降级

Cron 任务、API 调用等无 UI 的场景下,审批通道无法弹出 UI。降级行为可配置

降级模式 行为 适用场景
allow 自动放行,不阻塞 可信自动化任务
deny 自动拒绝 高安全要求环境
policy_only 跳过审批,仅走策略引擎 推荐默认值
json 复制代码
{
  "approval": {
    "non_interactive_fallback": "policy_only"
  }
}

白名单机制

支持两维度白名单,减少重复审批:

json 复制代码
{
  "tools": ["list_dir", "read_file", "exec:git *", "exec:npm run *"],
  "paths": ["/Users/me/projects/**", "https://api.example.com/*"]
}
  • tools 维度tool_nametool_name:command_pattern(glob 通配符)
  • paths 维度 :glob 模式匹配 path / url 参数
  • 匹配规则 :两个维度都匹配时才自动放行。无路径参数的工具(如 exec)自动跳过 paths 维度检查

七、执行环境抽象

透明沙箱(Transparent Sandbox)

工具在用户环境执行,通过策略/钩子/审批控制行为。

子模式 执行方式 适用场景
transparent 宿主机直接执行 开发环境、可信场景
restricted 宿主机子进程执行 + setrlimit 资源限制 需要资源防护但不需要完全隔离

restricted 模式的资源限制:

python 复制代码
resource.setrlimit(resource.RLIMIT_AS, (mem_limit,) * 2)     # 内存上限
resource.setrlimit(resource.RLIMIT_CPU, (cpu_limit,) * 2)    # CPU 时间上限
resource.setrlimit(resource.RLIMIT_NPROC, (nproc_limit,) * 2) # 进程数上限
resource.setrlimit(resource.RLIMIT_FSIZE, (fsize_limit,) * 2) # 单文件大小上限

隔离沙箱(Isolated Sandbox)

整个 Agent 进程(含安全层)运行在容器内,与宿主机物理隔离。

arduino 复制代码
宿主机                              容器
┌─────────────────────┐      ┌─────────────────────┐
│ Shell / 前端 UI     │      │ Gateway + Agent     │
│                     │ HTTP │ + 安全层(同一份代码)│
│ AdapterManager      ├─────→│                     │
│ (spawn 或 docker run)│  WS  │ 所有工具在此执行     │
└─────────────────────┘      └─────────────────────┘

核心设计 :安全层代码在两种沙箱中零改动复用 。透明沙箱下直接执行,隔离沙箱下 docker run <your-agent-image>,同样的代码、同样的策略、同样的插件钩子。

Volume 挂载策略
数据 挂载方式 理由
Agent 配置 (config.json) 只读 容器不能改配置,改配置只能通过宿主机
会话数据 (sessions/) 读写 切换模式后历史无缝延续
安全策略/插件 只读 容器内不能篡改安全规则
用户工作区 用户决定 挂不挂、只读还是读写,是用户的安全/便利权衡
网络隔离
模式 网络 适用场景
--network bridge 容器可访问互联网 Agent 需要调用 LLM API、web_fetch
--network none + 宿主机 LLM 代理 容器完全无网络 最高安全级别,API Key 不进容器

--network none 模式下,宿主机运行轻量 HTTP 代理,容器内的 LLM 请求通过代理转发,代理注入真实 API Key。这是实现真正网络隔离的唯一路径------否则容器要么无法调用 LLM,要么能访问任意网络地址。

切换机制

客户端在设置中切换执行环境(宿主机 / 容器),重启生效。这是运行时配置,不是安全策略------安全策略在两种环境下同样适用。


八、安全维度全景

六个安全维度,每个维度由框架的具体组件覆盖:

8.1 数据安全

威胁:Agent 读到敏感数据,数据进入 LLM 上下文后不可控。

控制点

阶段 组件 手段
执行前 策略引擎 (Before) 路径 ACL --- denied_paths 拒绝 .env / *.pem / ~/.ssh/**
执行后 DLP 扫描 (After) 结果敏感数据分类 → CRITICAL 阻断 / HIGH 脱敏

内置 DLP 模式:

类别 检测内容 级别
CREDENTIAL API Key、密码、私钥、AWS Key、GitHub Token CRITICAL
PII 身份证号、手机号 HIGH
FINANCIAL 银行卡号 HIGH

插件可通过 DLP_PATTERNS 扩展自定义模式。

8.2 操作安全

威胁:Agent 执行破坏性操作。

控制点

组件 手段
策略引擎 exec.denied_commands 正则黑名单(sudo、rm -rf /、curl | bash 等)
策略引擎 write_file.denied_paths 保护系统目录和构建文件
审批通道 关键操作前人类确认

8.3 系统安全

威胁:Agent 耗尽系统资源(fork bomb、死循环)。

控制点

组件 手段
执行环境 (restricted) 子进程隔离 + setrlimit 资源限制
执行环境 (isolated) Docker --memory 512m --cpus 1.0 --read-only
OS 级加固 seccomp-bpf(Linux)、sandbox-exec(macOS)

8.4 网络安全

威胁:Agent 访问不该访问的内部服务或向外泄露数据。

控制点

组件 手段
策略引擎 web_fetch.allowed_domains / denied_domains
策略引擎 exec.denied_commands 拦截 curl/wget/ssh/nc
执行环境 (isolated) Docker --network none + 宿主机 LLM 代理

8.5 权限安全

威胁:Agent 通过 spawn 创建不受控子 Agent,通过 cron 持久化任务。

控制点

组件 手段
策略引擎 spawn.max_concurrentspawn.inherit_policy
策略引擎 cron.action: deny(默认禁止,需审批放行)
安全层 类级别替换确保子 Agent 自动继承安全层,无逃逸路径

8.6 合规审计

威胁:出了安全事件无法追溯。

控制点

组件 手段
审计系统 每次工具调用产生结构化审计记录
After Hook 可对接企业 SIEM / ELK

审计记录格式:

json 复制代码
{
  "ts": "2026-03-04T14:23:15.123Z",
  "session_id": "sess-abc-123",
  "agent_id": "main",
  "sandbox_mode": "transparent",
  "policy_mode": "enforce",
  "tool": "read_file",
  "params": {"path": "/workspace/config/db.yml"},
  "decision": "allowed",
  "decided_by": "policy",
  "duration_ms": 12,
  "dlp_findings": [{"category": "CREDENTIAL", "level": "CRITICAL"}],
  "dlp_action": "redacted",
  "result_size_bytes": 1523
}

关键字段说明:

字段 说明
session_id 会话标识,关联同一对话的所有工具调用
agent_id 区分主 Agent 和子 Agent(spawn 产生的)
sandbox_mode 执行时的沙箱环境
policy_mode 执行时的策略模式
decided_by 谁做的决策:policy / hook:插件名 / approval

九、集成指南:如何对接你的 Agent 引擎

通用方法论

在任意 Agent 项目中应用本框架,只需三步:

  1. 找到咽喉点 :Agent 引擎中所有工具调用的唯一出口(通常是某个 execute() / run() / invoke() 方法)
  2. 运行时替换:用安全层包装原始方法,注入三阶段流水线
  3. 配置策略:提供外部策略文件,不硬编码安全规则

按语言的注入思路

不同语言有不同的运行时织入手法,但核心模式一致------保存原始方法 → 包装三阶段流水线 → 替换原始方法

Python Agent(如 nanobot)

思路 :monkey-patch 类方法。找到 ToolRegistry 的 execute() 类方法,保存原始引用,替换为包含三阶段流水线的 async wrapper。因为是类级别替换,所有实例(含 spawn 产生的子 Agent)自动继承。

ini 复制代码
original = ToolRegistry.execute
ToolRegistry.execute = wrapped_execute(original)

关键点:必须替换类方法而非实例方法,否则子 Agent 不会继承安全层。

Node.js Agent(如 OpenClaw)

思路 :原型链替换。通过 ToolRegistry.prototype.execute 替换原型方法,所有实例的调用自动经过安全层。也可以用 Proxy / Reflect 实现更细粒度的拦截。

ini 复制代码
original = ToolRegistry.prototype.execute
ToolRegistry.prototype.execute = wrappedExecute(original)

关键点:Node.js 的事件循环天然支持异步审批等待,无需额外线程模型。

Go Agent(如 PicoClaw)

思路 :接口适配器(Decorator 模式)。Go 没有 monkey-patch,但接口组合天然支持包装。定义一个 SecuredExecutor 结构体,内嵌原始 ToolExecutor 接口,在 Execute() 方法中注入三阶段逻辑。

scss 复制代码
SecuredExecutor{ inner: originalExecutor, policy: ... }
  → Execute() 中先 Before,再 inner.Execute(),再 After

关键点:Go 的接口隐式实现使得替换对调用方完全透明。

Rust Agent(如 ZeroClaw)

思路 :泛型 trait 包装。定义 SecuredTool<T: Tool>,对任意实现了 Tool trait 的类型 T 包装一层安全逻辑。编译期完成类型检查,运行时零开销。

r 复制代码
SecuredTool<T: Tool> { inner: T, policy: ... }
  → impl Tool for SecuredTool<T>
  → execute() 中注入 Before / Around / After

关键点:Rust 的所有权系统确保安全层包装后,外部代码无法绕过包装直接访问内部 Tool。ZeroClaw 本身已内置了 Docker sandbox runtime(runtime.kind = "docker"),说明行业对 Agent 执行环境隔离的需求正在快速增长。

MCP 工具的特殊处理

MCP(Model Context Protocol)正在成为 Agent 工具集成的事实标准。MCP 工具与内置工具的关键区别:

差异 内置工具 MCP 工具
工具名已知 编译时/启动时固定 运行时动态发现
参数结构 已知 schema 由 MCP Server 定义,安全层未必了解
执行位置 本地进程内 可能在远程 MCP Server

策略匹配 :对于动态工具名,策略引擎应支持通配符匹配(mcp:*mcp:filesystem:*)和默认规则(未匹配的 MCP 工具走 default_mcp_action)。

DLP 扫描:MCP 工具返回值结构不固定,DLP 应对序列化后的完整字符串做正则扫描,而非依赖特定字段。

网络访问:远程 MCP Server 本身是一个网络出口。策略引擎应能控制允许连接哪些 MCP Server(通过 URL 白名单),防止 Agent 被引导连接恶意 MCP 端点。

json 复制代码
{
  "tools": {
    "mcp:*": {
      "action": "allow",
      "allowed_servers": ["stdio://*", "http://localhost:*"],
      "denied_servers": ["http://*", "https://*"]
    }
  }
}

如果 Agent 引擎的 MCP 工具调用同样经过咽喉点(大多数引擎如此),则安全层自动覆盖 MCP 工具,无需额外适配。

关键注意事项

要点 说明
子 Agent 继承 确保安全层在类/trait 级别替换,而非实例级别,这样 spawn 的子 Agent 自动继承
异步兼容 Before Hook 可能需要等待用户审批(几秒到几分钟),确保替换后的方法支持异步
错误处理 安全层自身的异常不应导致 Agent 崩溃,应 catch 并降级为允许

十、参考实现概述

本框架已在一个基于 Python Agent 引擎的桌面 AI 助手项目中完整落地。以下是实现状态:

模块划分

实现分为四个核心模块,总计约 600 行 Python 代码:

模块 职责
SecurityLayer 核心协调器:monkey-patch 注入、策略加载、插件管理、三阶段流水线调度
PolicyEngine 策略引擎:JSON 策略解析、规则匹配、DLP 扫描、审计记录
ApprovalChannel 审批通道:异步 Future 管理、WebSocket 消息收发、连接断开处理
BuiltinPlugins 内置插件:交互式审批插件的自动安装与生命周期管理

已验证的能力

  • 三阶段流水线(Policy Gate + Hooks + DLP + Audit)--- 日常使用中稳定运行
  • 策略引擎(JSON 配置、热加载、enforce/monitor/disable 三模式)
  • 安全插件系统(同步 + 异步钩子、自定义 DLP 模式)
  • 交互式审批通道(WebSocket 双向通信 + 无超时 + 连接断开自动 deny)
  • 白名单机制(tools + paths 两维度 glob 匹配)
  • 内置插件自动安装(首次启动安装,用户删改后不覆盖)
  • 策略与钩子分离(内置策略受 mode 控制,插件钩子始终权威)
  • Hook message 字段(插件控制 Agent 侧可见消息,区分用户拒绝与策略阻止)

尚未实现

  • 隔离沙箱(Docker 容器执行环境)--- 架构已设计,待开发
  • restricted 子进程模式(setrlimit 资源限制)
  • 宿主机 LLM 代理(--network none 下的 API Key 隔离)

实现体会

约 600 行代码覆盖了透明沙箱的全部能力,核心原因是架构约束做得好:唯一咽喉意味着只需替换一个方法;三阶段流水线意味着每个阶段职责单一;插件系统通过目录扫描 + 约定接口实现,无需复杂的注册机制。


十一、落地节奏

阶段 做什么 前置条件
P1 透明沙箱上线(monitor 模式),全量记录工具调用,建立行为基线 咽喉点识别完成
P2 策略引擎调优(根据 P1 审计数据),安全插件开发,交互式审批上线 P1 数据积累
P3 enforce,高危工具启用 restricted 模式 P2 策略验证通过
P4 隔离沙箱(Docker)上线,宿主机 LLM 代理 容器化基础设施就绪
P5 对接 IAM/RBAC,策略中心化管理,多租户 企业级部署需求

十二、横向对比:现有 Agent 安全方案

方案 类型 工具执行拦截 策略引擎 人机审批 DLP 零侵入 容器隔离
Cursor IDE 内置 有(Run/Cancel) 无(硬编码) N/A
Claude Code CLI 内置 有(allowlist) 有(.claude 配置) N/A
ZeroClaw sandbox 运行时内置 有(allowlist + workspace scope) 有(config.toml) N/A 有(Docker)
PicoClaw sandbox 运行时内置 有(restrict_to_workspace) 有(命令黑名单) N/A 有(Docker)
本框架 外挂安全层 有(三阶段流水线) 有(JSON 热加载) 有(异步审批通道) 有(设计中)

关键差异

  • 内置方案(Cursor、Claude Code、ZeroClaw、PicoClaw)的安全能力与 Agent 引擎耦合,无法跨引擎复用,也无法独立于引擎升级迭代
  • 本框架作为外挂安全层,与 Agent 引擎完全解耦。同一套策略和插件可以应用于 Python、Node.js、Go、Rust 的不同 Agent
  • 现有方案普遍缺少 DLP(数据防泄漏)------工具执行结果中的敏感数据(API Key、PII)直接进入 LLM 上下文,无拦截
  • 现有方案的策略大多硬编码或仅支持简单配置,不支持插件式扩展热加载

十三、架构优势

安全层与 Agent 引擎完全解耦

markdown 复制代码
┌─────────────────────────────────────────┐
│          安全层(外挂模块)                │
│  策略引擎 / 插件 / 审批 / DLP / 审计     │
│  独立部署、独立升级、独立配置              │
└──────────────────┬──────────────────────┘
                   │ 运行时织入(零侵入)
                   ▼
┌─────────────────────────────────────────┐
│          Agent 引擎(任意)               │
│  nanobot / OpenClaw / PicoClaw / ZeroClaw│
│  独立演进、自由升级、社区同步              │
└─────────────────────────────────────────┘

这意味着:

  • Agent 引擎可以持续升级:上游发布新版本直接升级,安全层不受影响
  • 安全层独立迭代:策略更新、新增 DLP 模式、接入 SIEM------都不需要动 Agent 引擎
  • 不 fork、不魔改:彻底避免 fork 开源项目后跟不上上游的困境
  • 可插拔:想关掉安全层?移除注入代码重启即可,Agent 恢复原样
  • 跨引擎复用:同一套安全策略和插件可应用于不同的 Agent 引擎

v1.0 | 2026-03-04 | Agent 工具执行安全框架 --- 从提案到架构设计 v0.2 | 2025-03-08 | 基于 nanobot (Python) 的企业级安全提案

相关推荐
银河麒麟操作系统2 小时前
服务器通用(全架构)【服务器存储系统原理与运维实践解析】技术文章
运维·服务器·架构
无巧不成书02182 小时前
React Native 深度解析:从架构到实战
react native·react.js·架构
V1ncent Chen2 小时前
从零学SQL 02 MySQL架构介绍
数据库·sql·mysql·架构·数据分析
蜜獾云2 小时前
Kafka(2)-kafka架构-基本原理
分布式·架构·kafka
IvanCodes2 小时前
二、Kafka核心架构与分布式存储
大数据·分布式·架构·kafka
常利兵2 小时前
深入理解Android ViewModel&SavedStateHandle:告别数据丢失,打造稳健UI架构
android·ui·架构
systemlover2 小时前
会会平台的技术架构
架构
智在碧得2 小时前
弹性智变!Knative+ACK 构建云原生伸缩架构,解锁降本稳流新范式
云原生·架构·knative