夜雨聆风学习资料网

ARTICLE · 1047159

Hermes 源码解读十一:权限、审批和沙箱,让 Agent 动手之前先有边界

Hermes 源码解读十一:权限、审批和沙箱,让 Agent 动手之前先有边界

全文约 1750 字,读完大约 3 分钟。

Hermes 源码解读十一:权限、审批和沙箱,让 Agent 动手之前先有边界

Agent 真正危险的地方,不是它会说错话。

而是它会动手。

它能跑命令、改文件、访问网络、调用浏览器、执行脚本、发消息、创建定时任务。

这些能力一旦接上,系统就不能只靠一句“请谨慎操作”。

我读 Hermes 的安全相关源码时,最明显的判断是:

Hermes 把工具执行当成有副作用的操作来治理,而不是把审批当弹窗功能。

这篇看 tools/approval.pyagent/tool_guardrails.pytools/environments/*tools/path_security.pytools/tirith_security.pydocs/security/network-egress-isolation.md

审批不是一层,而是多层

很多 Agent 项目处理危险命令,做法是:

检测到危险命令,问用户要不要继续。

Hermes 复杂得多。

它至少有这些层:

hardline block   → yolo / approval mode 判断   → dangerous command detection   → Tirith 扫描   → smart approval   → CLI / Gateway approval surface   → session/permanent approval cache

这里最重要的是第一层:hardline block。

源码里明确有一些命令会被无条件阻断。

比如 rm -rf /mkfs、对裸设备写入、shutdown/reboot、fork bomb、kill -1 这类。

它们在 yolo 之前就被拦。

这个顺序非常关键。

yolo 不是系统底线的绕过券。

用户可以选择减少确认,但不能让系统执行明显不可恢复的灾难命令。

这是安全系统里很成熟的思路:

可恢复风险   → 可以审批  不可恢复风险   → 直接阻断

Gateway 审批不是弹窗,而是异步会话流程

CLI 里审批相对简单,终端里问用户即可。

Gateway 就复杂多了。

用户可能在 Telegram、Slack、Discord 或其他平台上发起任务。

Agent 在线程里跑到一半,命令需要审批。

这时不能让后台线程傻等一个不存在的 stdin。

Hermes 在 approval.py 里有 Gateway approval queue。

它会把 approval request 发回对应会话,Agent 线程阻塞等待用户 /approve 或 /deny,同时还要考虑 timeout、hook、session activity、清理队列。

这说明审批是运行时协议的一部分。

不是 UI 细节。

如果你做多平台 Agent,这点很重要:

审批结果必须能从用户所在的平台回到正在执行的 Agent 线程。

否则 Gateway 场景下的安全交互会断掉。

Tool guardrail 防的是“模型一直撞墙”

审批主要处理危险。

agent/tool_guardrails.py 处理的是另一类问题:模型重复调用同一个失败工具,或者一直没有进展。

比如:

  • • 同一个命令失败 5 次;
  • • 同一个工具路径无进展;
  • • 重复读取不存在的文件;
  • • 一直用相同参数调用失败 API。

Hermes 会生成 synthetic tool result,告诉模型不要继续重复这条路径。

这类 guardrail 不像安全审批那么显眼,但非常实用。

因为 Agent 失败时经常不是“想作恶”,而是卡在一个错误循环里。

对长任务来说,防止无意义重复,也是稳定性的一部分。

沙箱不是一个开关,而是一组后端

Hermes 的 terminal backend 不只有 local。

tools/environments/ 下面有 local、docker、ssh、modal、daytona、singularity 等后端。

不同后端的风险边界不一样:

后端
风险特点
local
直接操作本机,风险最高
docker
可隔离,但如果挂载 host path 仍有宿主风险
ssh
远端环境,凭证和目标机器风险独立
modal/daytona/singularity
更偏沙箱或托管执行环境

Hermes 在 approval 里也会考虑 env_type 和 host access。

如果 Docker sandbox 绑定了宿主路径,就不能简单认为“容器里执行所以安全”。

这点很现实。

很多团队把 Docker 当绝对安全边界,但一挂载项目目录、SSH key、Docker socket,风险就回来了。

沙箱不是标签。

沙箱要看它实际能碰到什么。

路径安全是小细节,也是大问题

tools/path_security.py 里有 validate_within_dir() 和 traversal 检查。

这类代码看起来很基础,但在 Agent 场景里很重要。

因为模型生成路径时,很可能出现:

../../.ssh/id_rsa ~/.env /etc/passwd

如果某个工具本来只允许访问 skill 目录、scripts 目录或 workspace,必须用 resolved path 检查它是否仍在允许根目录内。

字符串前缀判断不够。

要处理 symlink、..、绝对路径、home expansion。

Hermes 在 skills linked files、cron scripts 等地方都能看到类似边界。

这说明安全不是只在 terminal 命令上做。

每一个能读写路径的工具都需要边界。

网络出口隔离是另一层防线

Hermes 的安全文档里有一篇 Docker network egress isolation。

它讨论的是:即使 Agent 在容器里执行,如果默认 network_mode: host,命令仍然可以访问外网。

Prompt injection 最典型的攻击之一,就是诱导 Agent 通过 curl/wget/raw HTTP 把敏感信息发出去。

网络出口隔离的思路是:

agent core 在 internal 网络 需要外网的 gateway / proxy 在 egress 网络 出站走 allowlist proxy

这不是替代 sandbox。

它是第二层。

就算命令被执行了,也不应该默认能访问任意外部地址。

对企业 Agent 平台来说,这一层非常关键。

这套安全设计给我的启发

Agent 安全不能只靠一个“确认按钮”。

至少要分层:

解决什么
hardline block
不可恢复灾难命令直接拒绝
approval
可恢复但有风险的操作交给用户确认
guardrail
阻止重复失败和无进展循环
sandbox backend
限制命令实际执行环境
path security
防止工具越权读写
network egress
防止任意外联和数据外泄
checkpoint
给可恢复改动留回滚空间
audit/log
出问题后能追溯

这里面每一层都不完美。

但叠在一起,系统才有可能接近可用。

我的判断是:

Agent 越能干活,安全边界越要靠运行时设计,而不是靠提示词约束。

提示词可以提醒模型。

但真正执行命令的是工具系统。

真正能阻断危险的是 approval、hardline block、sandbox、path validation、network policy。

Hermes 不是一个完美安全系统,但它的源码至少在认真面对这个问题。

这也是从 demo 走向运行时必须补上的一课。

前面拆了入口、主循环、工具、Prompt、Provider、Gateway、Session、Plugin、Skill、Cron 和安全边界。最后要把它们放回一个更现实的问题:

如果我们要搭一个个人或小团队 AI 工作流系统,Hermes 这些设计到底哪些值得借鉴,哪些不该一开始就照搬?

如果你正在让 Agent 真正操作你的机器,建议先收藏这一篇。功能越强,越要先问清楚边界在哪里。

相关学习资料