09 - 安全与信任模型
学习目标
本章聚焦 Hermes Agent 的安全与信任模型。你将了解:
- 为何进程内没有任何组件构成对对抗性 LLM 的 containment
- 终端后端隔离与全进程包装的适用场景
- 审批门如何定位为”合作模式下的错误捕捉”
- 凭证作用域如何从子进程中剥离 API key
前置知识
本章涉及安全沙箱的通用原理,建议先阅读:
下文直接聚焦 Hermes 的信任模型具体实现。
项目实践
唯一安全边界:OS 级隔离
Hermes 的安全策略有一个核心原则,记录在 SECURITY.md 中:
进程内没有任何组件构成对对抗性 LLM 的 containment。
两层 OS 级隔离:
| 隔离类型 | 范围 | 适用场景 |
|---|---|---|
| 终端后端隔离 | 仅覆盖 shell/文件操作 | 可信 LLM + 防止误操作 |
| 全进程包装 | 整个 Agent 进程树 | 不可信输入源 + 生产部署 |
全进程包装支持 Docker Compose 和 NVIDIA OpenShell,后者提供声明式策略(文件系统、网络 L7 出口、进程/syscall、推理路由)。
安全含义:终端后端隔离仅覆盖通过 shell/文件操作执行的内容,不覆盖 Python 进程内的代码执行工具(作为宿主子进程运行)、MCP 子进程、插件加载或技能加载。
审批门:事故预防,不是安全边界
tools/approval.py 实现五层检测(详见工具注册与分发):
| 层级 | 检测内容 | 可绕过? |
|---|---|---|
| Hardline | rm -rf /、mkfs、fork bomb、dd 到块设备、shutdown/reboot | 不可(yolo 模式也不行) |
| Sudo stdin guard | 阻止密码猜测攻击 | 不可 |
| DANGEROUS_PATTERNS | ~47 个模式(递归删除、chmod 777、SQL DROP 等) | 用户确认 |
| Smart Approval | 辅助 LLM 评估风险 | 用户确认 |
| Tirith | 外部安全扫描 | 用户确认 |
关键设计:审批门明确定位为合作模式下的错误捕捉,不是对抗性防护。Shell 是图灵完备的,字符串黑名单在结构上是不完整的。
凭证作用域
Hermes 默认从传递给子进程的环境中剥离凭证:
| 子进程类型 | 凭证剥离 | 说明 |
|---|---|---|
| Shell 子进程 | 是 | API key、网关 token 不继承 |
| MCP 子进程 | 是 | MCP 进程不继承主进程凭证 |
| 代码执行子进程 | 是 | Python subprocess 剥离凭证 |
| 技能/插件 | 否 | 运行在 Agent 进程内,可读取所有上下文 |
技能/插件的凭证暴露:技能和插件作为宿主进程内的代码执行,可以访问 Agent 能读到的所有内容(包括 API key)。缓解措施是安装前审查,不是运行时脱敏。
输出脱敏与 Skills Guard
- 输出脱敏:终端工具输出中的敏感信息(如 API key 模式)在返回模型前被扫描和遮蔽
- Skills Guard:技能执行结果注入额外的扫描层,检测可能的凭证泄漏
问题与规避
进程内工具不受终端后端隔离保护
问题:Python 进程内的代码执行(execute_code)、MCP 子进程、插件/技能都在宿主进程中运行,不受 Docker/SSH 等终端后端隔离保护。
对策:需要完整进程隔离的场景使用全进程包装(Docker Compose / NVIDIA OpenShell),将 Agent 整个进程树放入容器中运行。
审批门的图灵完备性极限
问题:Shell 是图灵完备的,字符串模式匹配不可能覆盖所有破坏性操作。
对策:Hermes 明确将审批门定位为”合作模式下的错误捕捉”。对抗性场景需要 OS 级隔离,不能依赖审批门。
设计取舍
启发式防护的定位
| 定位 | 优势 | 代价 |
|---|---|---|
| 错误捕捉(Hermes) | 不误导用户、明确安全边界、减少虚假安全感 | 用户需要理解真正的安全边界在哪里 |
| 宣传为安全边界 | 用户感觉安全 | 被突破后造成实际损失 |
Hermes 选择在文档中明确说明审批门是启发式的、不构成 containment。这对于安全意识强的用户很重要——他们知道在对抗性场景下必须使用 OS 级隔离。
凭证剥离 vs 凭证继承
| 方案 | 优势 | 代价 |
|---|---|---|
| 默认剥离(Hermes) | 子进程泄漏凭证的风险低 | 某些需要 API 调用的子进程需要显式传递 |
| 默认继承 | 子进程自动可用 | 子进程被攻击时凭证全部泄漏 |
Hermes 选择默认剥离,因为”需要凭证”的场景可以显式传递,而”不需要凭证”的场景默认剥离减少了攻击面。
参考来源
- 源码验证:
SECURITY.md、tools/approval.py、tools/threat_patterns.py、tools/tirith_security.py