Open Interpreter 执行策略(execpolicy)实战:基于规则把命令分类为安全、风险与阻止
本篇技术指南围绕 Open Interpreter 的 Execution policy(执行策略)展开:它是叠加在沙箱之下的规则层,会在每一条命令真正执行前完成一次"体检"并把命令标记为
safe/unsafe/forbid。读完本文,你将掌握如何在config.toml中编写规则、理解它与审批(approval)流程的衔接方式,并能借助仓库自带的引擎与execpolicy check命令验证每一条规则是否真正按预期工作。
执行策略:沙箱之下的第一道规则层
Execution policy 位于沙箱(sandbox)之下,是代理执行命令前的第一道过滤。它不像沙箱那样从操作系统层面约束进程能力,而是直接"看"这条命令本身:在命令运行之前检查其内容并打上标签。打标结果决定这条命令后续走哪条路径——直接放行、交由审批,还是一律拒绝。
Open Interpreter 为每条命令分配三类标签:
| 标签 | 含义 |
|---|---|
safe |
常规、低风险。无需提示直接通过。 |
unsafe |
可能改变系统状态。需要审批。 |
forbid |
始终阻止。 |
Open Interpreter 随附一套合理的默认策略,大多数用户从不编辑它。只有当你想获得更严格的控制,或运行在共享系统(shared system)上时,才需要阅读本文并自定义规则。
策略存放位置:config.toml 与规则评估顺序
策略从 config.toml 加载。每一条规则由两部分构成:一个匹配命令的模式(pattern),以及一个动作(action)。规则以 TOML 数组的形式写在 [[execpolicy.rules]] 小节下:
[[execpolicy.rules]]
match = "ls"
action = "safe"
[[execpolicy.rules]]
match = "rm *"
action = "unsafe"
[[execpolicy.rules]]
match = "rm -rf /"
action = "forbid"
评估时有一个极其关键、也是最容易踩坑的语义:规则从上到下逐条评估,第一条命中的规则生效(The first match wins)。
这意味着:
- 把
match = "rm -rf /"写在其父模式rm *之后是安全的——因为rm -rf /本身就是rm *的子集匹配,从上到下先命中通用规则则后面的forbid永不生效; - 想让"特例"覆盖"通例",必须把更具体的规则放在更靠前的位置;
- 模式使用类 shell 的通配符(shell-style globs),例如
rm *中的*、pnpm test*中的*都属于这类通配符匹配。
三档标签与审批模式的交互方式
执行策略是代理的"第一道过滤"。策略对命令打标之后:
forbid:直接阻止命令,完全不进入后续环节;safe:在不提示(without prompting)的情况下直接运行;unsafe:交由你的审批模式(approval mode)处理,参见沙箱与审批。
由此可以推出两条非常实用的性质:
- 一条
safe规则可以显著减少你一天中弹出的审批次数——你信任的命令(例如测试、lint)不再打扰你; - 一条
forbid规则则提供"兜底"保证:即使你在审批提示中意外按下y,该命令也永远不会执行。forbid的拦截发生在审批之前,审批根本不会有机会放行它。
从仓库中新一代执行策略引擎的源码可以印证这套语义:核心决策类型 Decision 定义在 codex-rs/execpolicy/src/decision.rs,包含三档:
Allow:无需进一步审批即可运行;Prompt:请求用户明确批准;当以approval_policy = "never"(永不批准)模式运行时会被直接拒绝;Forbidden:不做任何考虑直接阻止。
可以推断,本文面向的 config.toml 三档标签 safe / unsafe / forbid 与上述三档决策在语义上一一对应:safe ≈ allow(免审批放行)、unsafe ≈ prompt(交由审批)、forbid ≈ forbidden(无条件拦截)。此外,当一条命令同时命中多条规则时,引擎会取最严格的严重级别作为最终决策(forbidden > prompt > allow),也就是说只要有任何一条规则把它判为 forbidden,命令就不会执行。
常见模式:直接可复用的规则片段
让你信任的 lint 与 test 命令完全不触发提示
把代理会反复执行、且你完全信任的命令标记为 safe,可以让日常工作流中的干扰降到最低:
[[execpolicy.rules]]
match = "pnpm test*"
action = "safe"
[[execpolicy.rules]]
match = "pnpm lint*"
action = "safe"
pnpm test* 这类前缀模式能同时覆盖 pnpm test、pnpm test --run、pnpm test:watch 等各种变体。
对所有破坏性操作强制确认
对可能改变远端状态或造成不可逆后果的命令,用 unsafe 强制人工确认,用 forbid 直接封死:
[[execpolicy.rules]]
match = "git push --force*"
action = "unsafe"
[[execpolicy.rules]]
match = "drop database*"
action = "forbid"
drop database 这类操作即便是开发库也几乎不该由代理自动执行,因此用 forbid 而不是 unsafe 是更稳妥的默认选择——毕竟 unsafe 只代表"需要审批",而审批仍可能被人为放行。
验证规则:execpolicy check 命令
模式采用类 shell 通配符,手写时容易出偏差。在把这些规则用于自动化之前,务必先用内置命令实测。文档给出的用法是:
interpreter execpolicy check '<command>'
例如:
interpreter execpolicy check 'pnpm test --run unit'
interpreter execpolicy check 'rm -rf /'
结合仓库实现可以进一步理解这条命令的机制。对应的子命令参数定义在 codex-rs/execpolicy/src/execpolicycheck.rs:它支持一个或多个 --rules <PATH> 策略文件、--pretty(美化 JSON 输出)以及 --resolve-host-executables(解析宿主可执行文件的绝对路径),命令本身以 trailing_var_arg 方式接收完整命令行 token。从 CLI 运行同样效果的检查:
codex execpolicy check --rules path/to/policy.rules git status
传入多个 --rules 时,多个策略文件会按传入顺序合并评估;加上 --pretty 可以获得格式化 JSON:
codex execpolicy check \
--rules path/to/policy.rules \
--pretty \
git push --force origin main
检查结果以 JSON 形式输出,包含命中的规则与最终决策:
{
"matchedRules": [
{
"prefixRuleMatch": {
"matchedPrefix": ["git", "push", "--force"],
"decision": "prompt",
"justification": "force push rewrites remote history"
}
}
],
"decision": "prompt"
}
关键字段的含义(与策略文件评估一一对应):
matchedRules:列出所有前缀命中了该命令的规则;一条命令可能命中多条规则,最终决策取最严格者;matchedPrefix:实际命中的命令前缀 token;resolvedProgram:仅当通过 basename 回退命中绝对可执行路径时才出现;decision:整体有效决策(allow/prompt/forbidden)。当没有任何规则命中时,matchedRules为空数组,decision字段被省略。
开发期间也可以直接用独立 dev 二进制运行:
cargo run -p codex-execpolicy -- check --rules path/to/policy.rules git status
源码透视:新一代 execpolicy 引擎与规则格式
仓库中的 codex-rs/execpolicy 是这个执行策略能力的新一代 Rust 实现(其使用说明见 codex-rs/execpolicy/README.md),旧式规则匹配器则位于 codex-execpolicy-legacy。新一代引擎以 prefix_rule 前缀规则 + host_executable 宿主可执行文件元数据为最小抽象:
prefix_rule(
pattern = ["cmd", ["alt1", "alt2"]], # 按序匹配的 token;列表表示可选项
decision = "allow", # allow | prompt | forbidden,默认 allow
justification = "explain why this rule exists",
match = [["cmd", "alt1"], "cmd alt2"], # 必须能命中的示例(加载期校验)
not_match = [["cmd", "oops"], "cmd alt3"], # 必须不命中的示例(加载期校验)
)
两个值得注意的工程细节:
-
match/not_match是规则的"单元测试"。在策略文件加载时,这些示例调用就会被校验(字符串会被shlex分词成 token 数组),确保模式表达与预期一致。仓库中的完整示例见 codex-rs/execpolicy/examples/example.codexpolicy,其中ls、cat这类无显式decision的规则默认即allow,而git reset --hard被声明为forbidden并附有justification("destructive operation"),cp则被标为prompt。 -
绝对路径与 basename 的匹配策略。引擎总是优先尝试精确的"首 token"匹配;在未开启宿主可执行文件解析时,
/usr/bin/git status只会命中首 token 为/usr/bin/git的规则;开启后则可能回退到针对git的 basename 规则。若存在host_executable(name = "git", paths = [...])声明,则 basename 回退只允许命中列表中列出的绝对路径;若某 basename 没有任何host_executable()条目,则 basename 回退不受限制。这种设计把"机器上到底哪个git被调用"也纳入了策略考量,适合共享/多用户环境。
另外,引擎还内置了针对 approval_policy="never" 等运行模式的行为(prompt 在该模式下直接被拒绝),这也解释了为什么 unsafe/prompt 在"永不批准"场景下等效于被拦截,而 forbid/forbidden 在任何场景下都无法绕开。
随附的默认策略长什么样
前面提到"Open Interpreter 随附一个合理的默认策略",仓库中旧式引擎的默认策略文件 codex-rs/execpolicy-legacy/src/default.policy 展示了这套默认策略的典型形态:它针对 ls、cat、cp、head、printenv、pwd、rg、sed、which 等高频命令分别用 define_program(...) 描述其合法 flag、参数类型与可接受的调用形态(should_match / should_not_match),例如:
ls只放行-1/-a/-l与"文件或当前目录"类参数;cat允许读取文件、-n/-b等常规 flag,但不放行无参数读 stdin 的形态;sed由于 GNU 实现存在s/.../.../e会执行 shell 命令的潜在风险,仅支持被白名单化的"已知安全"命令子集(如-n、-u,刻意不支持-i与-f)。
从这套策略可以看出默认策略的取向:让"读操作类"命令尽量静默放行,让可能改变状态或产生副作用的用法退回到人工审批,从根上排除高危形态。理解这一点,有助于你在自定义规则时把握 safe / unsafe / forbid 的分寸。
编写策略时的注意事项
- 顺序即优先级:规则从上到下评估、第一条命中生效。书写时把最具体、最想"特判"的规则(尤其
forbid)放在最前面,防止被前置的宽泛safe规则吞掉。 - 为
forbid提供替代建议:仓库的新格式规范建议,当decision = "forbidden"时,在justification中附上推荐的替代命令(例如"Use jj instead of git.")。这让代理在被拒绝时知道下一步该怎么走,而不是僵在原地。 - 用自动化测试心态写模式:把规则的
match/not_match示例当成测试用例维护——每次改动策略后,都用execpolicy check验证目标命令的判定结果再投入到自动化流程。 - 共享系统上宁严勿松:默认策略适用于单人开发机;在共享系统上建议收紧规则面,并对所有可能改写状态的命令显式声明
unsafe或forbid。 - 预览期注意事项:新一代
execpolicy命令目前仍处于 preview 阶段(见 codex-rs/execpolicy/README.md 的说明),其 API 在未来可能发生破坏性变更,将策略文件纳入版本管理、并在升级后回归测试是一个稳妥的做法。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00