雨天小六

读懂 Codex(9.12):Approval、Exec Policy 与可替换 Sandbox Adapter

· 更新于 2026-08-03 · 专栏:读懂 Codex

#Codex#Agent Runtime#Python#软件架构

具体问题与边界

规则决策、人工授权与操作系统隔离为什么必须是三层独立机制?

ExecPolicy 对 argv 产生 allow/prompt/forbid;ApprovalPolicy 处理 prompt;ExecutionEnvironment/Sandbox Adapter 执行命令。WorkspacePolicy 只做应用层路径检查。 本节区分“从官方源码得到的生产事实”和“为教学实现作出的 Python 选择”,不会把后一种包装成 Codex 的等价实现。

状态所有权

对象所有者生命周期持久化
ExecRule listExecPolicy配置生命周期Mini 不持久化
ExecDecisionExecPolicy.decide一个 argv
Approval responseHost/ApprovalPolicy一个动作或会话Mini 仅返回 bool
Sandbox AdapterSessionSession 生命周期
OS enforcement具体 sandbox backend进程生命周期外部安全边界

正常路径

Approval、Exec Policy 与可替换 Sandbox Adapter正常路径图
图 9.12-1:规则决策、人工授权与操作系统隔离为什么必须是三层独立机制?
  1. ExecPolicy 用 argv token prefix 匹配,匹配多个规则时 Mini 取最长 prefix;未匹配走 default。它不解析 shell script 内部语义。
  2. forbid 不询问用户,直接拒绝;prompt 才进入 Approval;allow 只表示应用策略许可。
  3. Approval 是用户/Host 决策,不会给进程增加文件系统或网络隔离能力。
  4. Session 注入 ExecutionEnvironment Protocol。LocalSandboxAdapter 只是委托本地环境,类文档明确声明无 OS isolation;DenyAll adapter 用于证明边界可替换。
  5. WorkspacePolicy.resolve 防止 Patch path 和 cwd 逃出根目录,但命令仍可自行打开绝对路径或联网。

顺序为什么不能交换

ExecPolicy 用 argv token prefix 匹配,匹配多个规则时 Mini 取最长 prefix;未匹配走 default
→ forbid 不询问用户,直接拒绝;prompt 才进入 Approval;allow 只表示应用策略许可
→ Approval 是用户/Host 决策,不会给进程增加文件系统或网络隔离能力
→ Session 注入 ExecutionEnvironment Protocol
→ WorkspacePolicy.resolve 防止 Patch path 和 cwd 逃出根目录,但命令仍可自行打开绝对路径或联网

箭头代表可见性与所有权转移,不是松散依赖。Policy、Approval、外部副作用、规范 Item 和 durability 各自有提交点,后一步不能替前一步作更强承诺。

Python 风格伪代码

decision = exec_policy.decide(argv)

match decision:
    case FORBID:
        return error_result("forbidden by exec policy")
    case PROMPT:
        if not await approval.approve(ActionRequest(argv, cwd)):
            return error_result("rejected by approval")
    case ALLOW:
        pass

# Approval is finished; enforcement is still a separate boundary.
result = await sandbox_adapter.run(
    argv,
    cwd=workspace_policy.resolve(cwd),
    timeout_seconds=timeout,
    cancellation=token,
)
return encode_tool_result(result)

class LocalSandboxAdapter:
    async def run(...):
        return await local_environment.run(...)  # deliberately no isolation

失败、取消与恢复

Approval、Exec Policy 与可替换 Sandbox Adapter失败路径图
图 9.12-2:每个失败点都列出已经发生的副作用和仍可安全执行的恢复动作。
故障点已留下的状态处理
规则 forbid不进入 Approval/执行模型可见 policy denial
Approval deny/timeout不执行命令模型可见 rejection
Local adapter 被误叫 sandbox形成虚假安全结论文档/类型明确 no isolation
真实 sandbox deny进程未创建或被限制编码具体 sandbox error
path check 通过但命令越权应用层无法阻止必须由 OS sandbox/remote executor 负责

不变量

Policy allow 与用户 approve 都不能被表述为 OS 隔离;只有实际执行 backend 能强制文件系统、网络和进程边界。

设计思路与限制

三层分离增加配置与错误类型,却能精确回答“谁允许了动作”和“谁真正阻止越权”。Mini 没有 Linux Seatbelt/bubblewrap、macOS Seatbelt、Windows restricted token/WFP。

测试与复现

cd examples/mini-codex
uv run pytest -q -k 'test_exec_policy_uses_longest_argv_prefix or test_approval_rejection_becomes_model_visible_result or test_workspace_policy_rejects_parent_traversal'
uv run mypy src
  • test_exec_policy_uses_longest_argv_prefix
  • test_approval_rejection_becomes_model_visible_result
  • test_workspace_policy_rejects_parent_traversal

官方源码导航

Mini Codex 对照

  • src/mini_codex/policy/exec_policy.py:最长 argv prefix 决策
  • src/mini_codex/policy/approval.py:可替换人工授权 Protocol
  • src/mini_codex/execution/sandbox.py:Local/DenyAll Adapter
  • src/mini_codex/policy/workspace.py:应用层路径边界

本节结论

Policy allow 与用户 approve 都不能被表述为 OS 隔离;只有实际执行 backend 能强制文件系统、网络和进程边界。

阅读导航

上一节:9.11 · 下一节:9.13

评论


← 返回文章列表