雨天小六

读懂 Codex(10.6):应用策略、人工审批和 OS 沙箱分层

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

#Codex#Agent Runtime#软件架构#系统设计

具体问题与边界

“用户点了允许”不能让进程读取任意密钥;“命令在沙箱里”也不能判断用户是否愿意删除仓库文件。 安全链至少包含威胁识别、策略分类、具体授权和系统强制执行。Codex 把 Permission Profile、Exec Policy/Guardian、Approval 与平台 Sandbox/Network Proxy 放在不同层,因为它们回答的问题不同。

本节不把 Hook 或路径检查宣传为安全边界,也不评价未公开云端内部实现。

四层责任

主要问题决策/状态不能替代
Permission Profile本次 Turn 可请求哪些资源cwd、读写根、网络、附加权限用户对具体动作的同意
Policy/Guardian这个具体动作风险如何allow、prompt、forbid/review内核级资源限制
Approval用户/Host 是否授权这次请求once/session scoped decision缩小过宽的系统能力
Sandbox/Proxy进程实际上能触碰什么OS profile、ACL/token、network rules理解用户意图

Pre Hook 可以加入组织规则,但它运行在应用协议边界;Post Hook 更不具备撤销已经发生副作用的能力。

正常决策链

权限画像、执行策略、人工审批和操作系统沙箱依次约束工具副作用的流程图
图 10.6-1:应用层先形成最小具体请求,审批只授权该请求,执行器仍在 OS 沙箱和网络规则内运行。
  1. TurnContext 从配置、受管要求和临时附加权限物化 Permission Profile。
  2. Handler 把模型参数解析为具体 argv、cwd、路径和网络意图,避免审批抽象描述。
  3. Exec Policy/Guardian 根据规则输出 allow、prompt 或 forbid;不可询问的拒绝不会伪装成审批。
  4. Prompt 分支用稳定 key 注册 waiter,批准只覆盖声明的作用域。
  5. 执行器把 Permission Profile 编译成平台 Sandbox/Proxy 约束,然后启动进程。
  6. 若检测到 SandboxDenied,只有政策允许时才能提出升级并以新权限重试一次。

官方公开说明同样把 sandbox mode 与 approval policy 区分:前者限制技术能力,后者决定何时必须询问。 这一产品概念与源码分层一致,但平台具体实现仍由锁定源码证明。

Python 风格伪代码

async def authorize_and_run(request: ExecRequest, context: TurnSnapshot) -> ExecResult:
    concrete = validate_and_resolve(request, cwd=context.cwd)
    permission = context.permissions.restrict_to(concrete.required_resources)
    verdict = exec_policy.classify(concrete)
    if verdict is Forbid:
        return ExecResult.denied("policy forbids this action")
    if verdict is Prompt:
        decision = await approval_waiters.request(concrete, context.cancellation)
        if decision is not Approved:
            return ExecResult.denied("approval not granted")
    environment = execution_environment.for_profile(permission)
    try:
        return await environment.spawn(concrete, context.cancellation)
    except SandboxDenied as denial:
        escalation = permission.minimal_escalation_for(denial)
        if not context.approval_policy.may_escalate(escalation):
            return ExecResult.denied(denial.explanation)
        await approval_waiters.request(escalation, context.cancellation)
        return await execution_environment.for_profile(escalation).spawn(concrete, context.cancellation)

这里 environment.spawn 不是万能黑箱:它代表由平台实现的进程启动和强制边界;应用策略不能假装 完成了这部分工作。

失败和绕过路径

仅依赖审批、策略、路径校验或沙箱单一层时的安全失效图
图 10.6-2:每一层都只覆盖一类失败;删除任何一层都会留下不同的可绕过缺口。
单层依赖遗漏威胁典型结果
只用 Tool description/Hook模型输入可绕过说明越界请求进入执行器
只用 Exec Policy规则不强制 syscall/path子进程仍可访问系统资源
只用 Approval用户难以审查隐含资源范围一次批准覆盖过宽能力
只用 cwd/路径检查命令内部可自行打开其他路径应用检查被解释器绕过
只用 OS Sandbox不理解业务意图与破坏性合法范围内仍可做用户不想要的事
失败后无限升级重试逐步扩大权限策略被错误循环消解

设计判断

分层会造成同一请求在多个模块中被表示,也需要把拒绝理由反馈给模型和用户。收益是各层可以使用 适合自己的证据和强制机制,并能单独测试。安全审计应问“每层的输入、输出和不可替代性”,而不是 只问“有没有沙箱”。

小型本地 Agent 即使不实现 Guardian,也至少应把应用 allowlist、人工确认和 OS 隔离分开;若没有 真实沙箱,必须像 Mini Codex 一样明确标记 Local Adapter 无隔离。

证据与 Mini Codex

生产锚点为 protocol/src/permissions.rscore/src/exec_policy.rscore/src/tools/sandboxing.rssandboxing/src/manager.rs 和平台后端。6.72—6.82 给出各层及 macOS/Linux/Windows/Network 分支。

Mini Codex 只实现 ExecPolicy、Approval、WorkspacePolicy 与可替换 Adapter:

cd examples/mini-codex
uv run pytest -q -k 'policy or approval or sandbox or workspace'

默认 LocalSandboxAdapter 没有 OS isolation,测试通过只证明决策顺序。

本节边界

已经证明:意图分类、授权和强制执行不可合并。下一节转向另一种常被错误合并的层次——持久化权威。 详细源码映射由研究仓库中的配套索引维护。

阅读导航

上一节:10.5 · 下一节:10.7

评论


← 返回文章列表