安全防护体系:当 Agent 拥有终端时如何防止「做出格」的事

Hermes 如何用工具守卫、危险命令审批、敏感路径保护、智能审批四道防线,约束 Agent 的破坏力

通过 Hermes 探秘 Agent 工程 | 第 5 篇 · 查看全部

上一篇:工具调度系统:从注册到执行的完整生命周期


[系列文章导航]

#文章定位
1Agent Loop:Agent 的核心执行循环入口
2System Prompt:身份、上下文与策略的三层架构认知层
3工具系统:从注册到调度工具层
4工具调度系统:从注册到执行的完整生命周期调度层
5安全防护体系:当 Agent 拥有终端时如何防止「做出格」的事安全层
6沙箱与代码执行:让 Agent 安全跑代码的 RPC 架构执行层
7上下文压缩:让 Agent 在有限窗口里「记得住」记忆层
8记忆系统:跨会话持久化的工程实现记忆层
9技能系统:Agent 如何把经验变成可复用的程序化记忆记忆层
10Provider 抽象层:让 Hermes 同时驾驭 30+ 个 LLM 提供商模型层
11Gateway 网关:连接 20+ 平台的统一消息路由接入层
12多 Agent 协作:委托、调度与看板协作层

问题:Agent 有「手」也有「破坏力」

上一篇文章,我们看到了 Hermes 的工具调度系统如何让 Agent 高效地「做事」。但一个不愿忽视的问题是:当 Agent 拥有 terminal 权限时,它也能执行 rm -rf /

Agent 的安全风险来自几个层面:

  1. 循环失控:模型陷入死循环,反复调用同一个失败的工具,消耗 API 额度(详见 第 4 篇:工具调度系统
  2. 破坏性命令:模型误操作或「幻觉」生成危险指令(rm -rf /git push --force 到主分支)
  3. 敏感路径访问:模型读取或修改安全策略文件本身(如 ~/.ssh/~/.hermes/config.yaml
  4. 错误信息注入:工具返回的错误字符串里包含 </tool_call> 等结构标记,欺骗模型进入错误状态

Hermes 用四道防线构建了纵深防御体系。

第一道防线:工具调用守卫(Tool Guardrails)

三类循环检测

ToolCallGuardrailController 跟踪每轮的工具调用模式,检测三种循环:

类型含义触发条件(默认)
Exact Failure Loop同一工具 + 同一参数连续失败warn ≥ 2 次 / block ≥ 5 次
Same Tool Failure Loop同一工具连续失败(不论参数)warn ≥ 3 次 / halt ≥ 8 次
No Progress Loop幂等工具反复返回相同结果warn ≥ 2 次 / block ≥ 5 次

签名机制

「相同的工具调用」不是通过字符串比对来识别的——Hermes 会对参数做规范化处理:

canonical = json.dumps(args, sort_keys=True, separators=(",", ":"))
signature = sha256(canonical)  # 稳定、不可逆、不暴露参数值

两种守卫模式

警告模式(默认):不阻止执行,只是在工具结果后追加一条提示。模型看到这条消息后应该改变策略。

硬停止模式(opt-in):通过配置 hard_stop_enabled: true 开启。当循环达到阈值,直接返回 blockhalt 决策。

工具分类

  • 幂等工具IDEMPOTENT_TOOL_NAMES):read_filesearch_filesweb_searchbrowser_snapshot 等——重复返回相同结果说明模型在「原地打转」
  • 变更工具MUTATING_TOOL_NAMES):terminalexecute_codewrite_filepatch 等——连续调用可能是正常的重试逻辑

第二道防线:危险命令审批

三种审批模式

模式行为适用场景
manual必须人工确认(默认)日常使用
smart用辅助 LLM 自动判断高频交互、信任环境
off不审批高风险—仅推荐沙箱环境使用

危险模式匹配

approval.py 定义了一系列正则表达式来检测命令中的危险操作:删除类(rm -rf)、强制推送类(git push --force)、磁盘操作类(ddmkfs)、Fork 炸弹、系统路径写入等。

macOS 特殊处理

macOS 的系统路径比较特殊——/etc/var/private/etc/private/var 的符号链接。Hermes 显式匹配了两种形式,防止通过符号链接绕过保护。

第三道防线:敏感路径保护

路径模式原因
~/.ssh/SSH 私钥——泄露意味着服务器沦陷
~/.hermes/.env环境变量——可能包含 API 密钥
~/.hermes/config.yamlAgent 的安全策略本身——如果 Agent 能自行关闭审批……
*.env*.env.*项目级环境变量文件
~/.netrc~/.pgpass凭证文件

自指保护config.yaml 本身既是安全策略的载体,也是被保护的对象。

第四道防线:工具结果清洗

_sanitize_tool_error() 对错误字符串做清洗——去除 framing tokens(如 </tool_call>、Triple backticks)、转义 CDATA 标记、防止 fence tokens 出现在错误文本中。

四道防线的协同工作

模型发出 tool_calls
       │
       ▼
┌─────────────────────────────────────────────┐
│  Tool Guardrails (per-turn 循环检测)         │
└─────────────────────────────────────────────┘
       │
       ▼
┌─────────────────────────────────────────────┐
│  危险命令审批 (terminal 专用)                 │
│  ├─ 危险模式匹配                              │
│  ├─ 敏感路径检查                              │
│  ├─ 审批模式分支 (manual / smart / off)      │
│  └─ 白名单检查                                │
└─────────────────────────────────────────────┘
       │
       ▼
┌─────────────────────────────────────────────┐
│  前置 Checkpoint (Git snapshot)              │
│  ├─ write_file / patch → 确保可回滚          │
│  └─ destructive terminal → 确保可回滚        │
└─────────────────────────────────────────────┘
       │
       ▼
  工具实际执行
       │
       ▼
┌─────────────────────────────────────────────┐
│  后置处理                                    │
│  ├─ _sanitize_tool_error() → 清洗错误字符串  │
│  ├─ post_tool_call hook                      │
│  └─ 工具结果写入消息历史                      │
└─────────────────────────────────────────────┘

下一篇:沙箱与代码执行:让 Agent 安全跑代码的 RPC 架构 — execute_code 工具如何在隔离环境中安全运行代码