第 21 讲:Sandbox Manager 与策略转换

Codex 源码解析 · 第 21 讲

Codex 源码解析系列 第 21 讲:Sandbox Manager 与策略转换 基于 OpenAI Codex 源码 · 2026-10-15 💡 本讲一句话: Codex 把"要不要沙箱"拆成两个独立问题——策略上该不该(should_sandbox)和平台上能不能(get_platform_sandbox),再由 transform() 按后端生成可启动的 argv;命令被杀后,violation.rs 用关键词 + SIGSYS 指纹反推"是不是沙箱干的"。读完你能看懂 sandboxing crate 三个核心文件如何把权限声明变成 OS 强制。 一、定位:权限声明与 OS 强制之间的"翻译器" 上一讲(第 20 讲)拆完工具并行执行层,命令已经过了审批。但"批准执行"不等于"裸跑"——Codex 对每条 shell 命令都默认持有一个保守假设: 模型生成的命令不可信 。它可能写错路径、被提示注入带偏、或者单纯地 rm -rf 到声明范围之外。 于是每个平台都有自己的强制机制:macOS 用 Seatbelt(sandbox-exec + .sbpl 策略文件),Linux 用 bwrap 命名空间 + Landlock/seccomp,Windows 用受限令牌。三套机制 API 完全不同、参数形态不同、失败表现也不同。 sandboxing crate(约 4K LOC)就是这个"翻译器": 输入是声明式的 PermissionProfile (可写根目录列表 + 网络开关), 输出是命令式的、可直接 spawn 的 argv 。三个核心文件分工明确: 🔹 manager.rs(776 行) :决策 + 分发——要不要沙箱、选哪个后端、生成最终 argv; 🔹 policy_transforms.rs(670 行) :策略转换——基础权限与临时升级的合并、"是否需要平台沙箱"的统一判定; 🔹 violation.rs(297 行) :违规归因——命令失败后判断是不是沙箱拦的,提取被拒路径喂给模型。 本讲按"决策 → 转换 → 归因"的顺序逐行拆。第 22-24 讲再深入各平台后端内部(bwrap、Landlock/Seatbelt、Windows)。 二、两个独立问题:该不该沙箱?能不能沙箱? manager.rs 开头先定义了两个枚举——一个是"后端类型",一个是"用户偏好"。注意它们被刻意分开:前者是 能力 (这个平台有什么),后者是 策略 (用户要什么)。 📄 codex-rs/sandboxing/src/manager.rs (第 41-81 行) #[derive(Clone, Copy, Debug, PartialEq, Eq)] // 派生常用 trait:可按值拷贝、可比较、可调试打印 pub enum SandboxType { // 四种沙箱后端 + None,是后面所有分发的"目标类型" None, // 不沙箱:直接跑(权限已是全盘可写,或用户显式禁止) MacosSeatbelt, // macOS Seatbelt(sandbox-exec),策略文件 .sbpl LinuxSeccomp, // Linux bwrap + Landlock/seccomp 组合(名字叫 seccomp,实为多机制叠加) WindowsRestrictedToken, // Windows 受限令牌沙箱 } // 闭合外层代码块 #[derive(Clone, Copy, Debug, PartialEq, Eq)] // 偏好枚举同样可拷贝、可比较 pub enum SandboxablePreference { // 用户级偏好:是否允许使用平台沙箱 Auto, // 自动决策:按权限画像判断(默认值) Require, // 必须用沙箱;平台不可用时直接失败,绝不裸跑 Forbid, // 禁止用沙箱(典型场景:已经在外层沙箱里,避免嵌套) } // 闭合外层代码块 pub fn get_platform_sandbox(windows_sandbox_enabled: bool) -> Option<SandboxType> { // 把"当前 OS"映射到可用后端——纯能力问题 if cfg!…

阅读全文:Codex 源码解析 第 21 讲