为在 Windows 上启用 Codex 构建安全、高效的沙盒
OpenAI 为 Windows 上的 Codex 开发了自定义沙盒实现,以消除用户在低效的手动命令批准和无限制的“完全访问”模式之间进行选择的需求。该沙盒允许 Codex 广泛读取文件,同时将写入权限限制在特定工作区,并阻止未授权的网络访问,使 Windows 上的体验与 macOS 和 Linux 上的 Codex 在安全性和可用性方面保持一致。
为什么现有的 Windows 隔离工具不足
OpenAI 评估了多种原生 Windows 隔离原语,但发现它们与开发者工作流的开放性(Shell、Git、Python 以及各种构建工具)不兼容。
- AppContainer:虽然提供了强大的操作系统边界,但它是为范围严格的应用程序设计的,对代码代理需要执行的各种二进制文件来说过于受限。
- Windows Sandbox:此轻量级虚拟机提供了强隔离,但不适用,因为 Codex 必须在用户的实际本地检出和环境中运行,而不是在一次性客体操作系统上。此外,它在 Windows Home 版本中不可用。
- Mandatory Integrity Control (MIC):使用低完整性标签被认为风险过大,因为将工作区标记为低完整性会使其成为主机上任何低完整性进程的“汇”,而不是仅向沙盒授予有针对性的访问权限。
“非提升沙盒”原型
第一个原型侧重于在没有管理员权限(非提升)的情况下运行,利用安全标识符(SID)和写入受限令牌来管理文件系统访问。
文件系统写入限制
为了控制 Codex 可以修改文件的位置,团队使用了合成 SID 与写入受限令牌的组合:
- Synthetic SIDs:创建了自定义
sandbox-writeSID,以在访问控制列表(ACL)中定义权限,而不干扰其他系统用户。 - Write-Restricted Tokens:这些令牌需要两项检查才能成功进行写入操作:必须允许普通用户身份,并且令牌的受限列表中至少有一个 SID(包括
sandbox-writeSID)也被授予访问权限。
这使得 Codex 能够获得对当前工作目录和已配置的 writable_roots 的写入/执行/删除权限,同时明确拒绝访问诸如 .git、.codex 和 .agents 文件夹等敏感区域。
网络访问限制
由于原型是非提升的,无法使用 Windows 防火墙。相反,它依赖于“建议性”限制,例如污染环境变量(HTTPS_PROXY、GIT_HTTPS_PROXY)以及在 PATH 前添加 denybin 目录以拦截 SSH 和 SCP 调用。该方法被发现过于薄弱,因为进程可以轻易绕过环境变量或直接打开套接字。
最终的“提升沙盒”架构
为实现强大的网络抑制,OpenAI 转向了需要在设置期间获取管理员权限以实施防火墙规则和专用系统用户的“提升沙盒”。
设置与权限
codex-windows-sandbox-setup.exe 二进制文件负责提升的配置:
- User Creation:它创建了两个本地用户:
CodexSandboxOffline(受防火墙规则阻止)和CodexSandboxOnline(不受阻止)。 - Credential Management:用户凭据通过 Windows 数据保护 API(DPAPI)加密。
- Firewall Rules:完全阻止
CodexSandboxOffline用户的出站网络访问。 - Read ACLs:由于沙盒用户与真实用户不同,设置会异步授予对关键目录的读取/执行权限(例如
C:\Users\<real-user>、C:\Windows\、C:\Program Files\),以确保代理仍能读取所需文件。
命令执行流程
由于 Windows 权限边界,codex.exe 不能直接以不同用户和受限令牌启动进程。这需要引入 codex-command-runner.exe 来拆分执行流程:
- Initiation:
codex.exe使用CreateProcessWithLogonW以指定的沙盒用户启动codex-command-runner.exe。 - Restriction:在运行器内部,进程打开自己的令牌,使用
CreateRestrictedToken创建受限令牌,然后使用CreateProcessAsUserW启动最终的子进程(例如 Python 脚本或 Git 命令)。
沙盒组件堆栈概述
最终架构由四个不同层次组成,以平衡安全性和开发者生产力:
codex.exe:主要的非提升驱动程序。codex-windows-sandbox-setup.exe:处理提升的设置、用户创建和防火墙配置。codex-command-runner.exe:生成受限令牌并以沙盒用户身份启动最终子进程。- The Child Process:代理在受限权限下实际执行的命令。