Windows Codex Computer Use 初始化失败:从 error 5 到最小 ACL 修复
这篇文章讲什么
本文复盘一次已修复的真实故障:Codex 的 Computer Use 在执行 JavaScript 之前就退出了,普通沙箱命令同样失败。
根本原因是运行 Codex 的普通用户对日志中报错的两个目录缺少 WDAC(更改权限)权限。管理员在这两个目录上补授 WDAC 后,沙箱刷新恢复正常,Computer Use 的初始化、应用枚举和窗口枚举随之恢复。
配套脚本把这一操作封装成可检查、可备份、可还原的流程。它不是 OpenAI 官方修复程序,也不是所有 Computer Use 故障的万能方案。必须先确认日志中存在同类 error 5 错误,再决定是否修复。
你也可以用以下提示词直接丢给codex,让它判断和修复:
根据 https://aibook.ren/archives/codex-computer-use-err 这篇文章判断当前是否是造成Computer Use无法使用的同样原因,如果是请参考文章怎么修复。1. 适用条件
以下四个条件同时满足,才适合按本文操作:
Windows 原生 Codex 沙箱启动或刷新失败(Computer Use 的 Node 内核也可能在执行 JS 之前退出)。
最新且与失败时间对应的日志中出现
SetNamedSecurityInfoW failed ...: 5,明确指出某个目录无法添加 deny/read ACE。该目录是本地普通目录,经核查所有者、DACL 和执行身份后,确认运行 Codex 的普通用户缺少修改该目录 DACL 的能力。
管理员同意为该用户授予目标目录的权限管理能力,并允许先备份再修改。
以下问题不在本文范围内: 插件未安装或被禁用、WindowsApps 插件源复制导致的 os error 6000/EFS 加密问题、账号或地区不支持、模型能力缺失、登录权限 error 1385、组织安全策略限制、网络问题、应用没有窗口、鼠标键盘操作失败、JSON 状态文件损坏。
⚠️ 如果报错目标是磁盘根、用户根、Windows、WindowsApps、Program Files、系统数据目录、符号链接、联接、加密目录或受管理的特殊目录,请停止自动修复,交管理员人工判断。不要为了让脚本通过而复制系统目录或修改其拒绝规则。
2. 本次案例:症状、证据与结果
本节保留实际路径供复盘。后续通用步骤通过参数输入,不要求读者具有相同用户名或盘符。
2.1 故障表现:业务代码尚未执行就已失败
通过 node_repl 初始化 @oai/sky,准备调用 sky.list_apps() 时内核退出,错误信息包括:
windows sandbox failed: helper_unknown_error: setup refresh had errors
trusted Node process exited unexpectedly普通 sandbox exec 同时失败。既然沙箱本身都无法创建/刷新,继续调试枚举窗口的 JavaScript 毫无意义——需要先解决沙箱层面的问题。
排查阶段使用经过授权的沙箱外只读命令查看日志,没有以关闭沙箱作为修复手段。
2.2 定位日志中的关键错误
实际主日志路径:
C:\Users\fengin\.codex\.sandbox\sandbox.2026-09-02.log同目录下的 sandbox.log 最后写入时间在 6 月,不能只看它。2026-09-02 14:56 左右(UTC+8)的故障,对应日志中 06:56...+00:00 的记录:
[2026-09-02T06:56:10.334303200+00:00] deny ACE failed on D:\code\work\inxvision-iot\.git: SetNamedSecurityInfoW failed for D:\code\work\inxvision-iot\.git: 5
[2026-09-02T06:56:10.379406500+00:00] grant read ACE failed on C:\Users\fengin\PCManger for sandbox_group: SetNamedSecurityInfoW failed: 5同一时段的 setup refresh 汇总报告 errors 非空。error 5 表示"访问被拒绝",关键是搞清楚哪个身份无法更改哪个目录的安全描述符。
2.3 "能写文件"不等于"能改权限"
这里有两个常见误解需要澄清:
Modify ≠ ChangePermissions:
Modify允许编辑或删除文件,但不包含ChangePermissions(即 WDAC)。属于 Administrators 组 ≠ 正在使用管理员令牌: 普通用户即使在 Administrators 组内,其普通进程也不会自动启用管理员令牌。
本次配置为:
[windows]
sandbox = "elevated"官方将 elevated 描述为使用专用低权限沙箱用户等边界的原生沙箱实现。它不等于"桌面主进程必须始终以管理员令牌运行",不能仅凭 GUI 的 TokenElevation=false 就判定异常。参见 OpenAI:Windows sandbox。
2.4 实际执行的最小修改
管理员在提权后的 PowerShell 中,先通过 icacls /save 分别备份两个目标目录的 DACL,再执行:
icacls.exe 'D:\code\work\inxvision-iot\.git' /grant 'AIBOOK\fengin:(WDAC)'
icacls.exe 'C:\Users\fengin\PCManger' /grant 'AIBOOK\fengin:(WDAC)'本机已修复完毕,以上两条仅用于复盘,无需重新执行。
修改范围非常克制:没有 /T(递归)、/reset、/setowner,没有删除、改继承,也没有给 Everyone 或沙箱用户增加写权限。修复后只读核验显示,两个目录各多了一条授予 AIBOOK\fengin 的 ChangePermissions Allow,仅作用于目录本身。
原备份位于:
C:\Users\fengin\.codex\backups\sandbox-acl-2642523518354441abde28cd7c924a83
git.acl 762 字节
pcmanager.acl 154 字节本次制作教程仅核对了原备份的大小和哈希,没有覆盖、修改、清理或打包原备份。
2.5 验收结果与边界
修复后,普通、无提权的 sandbox exec 成功执行,运行身份为 AIBOOK\CodexSandboxOffline。最新日志出现:
setup refresh: processed 3 write roots (read roots delegated); errors=[].git 目录出现了沙箱的 Deny 保护,PCManger 成功加入沙箱组的 ReadAndExecute。随着任务变化,processed ... write roots 的数量可能变化,不应把固定数字作为验收标准。
后续遇到的 EOF 问题: 第一次重试 Computer Use 时出现了另一类错误 apply deny-read ACLs,日志显示:
parse deny-read ACL state ...\deny_read_acl_state.json
EOF while parsing a value at line 1 column 0该状态文件随后自行恢复为有效的 22 字节 JSON(根字段为 principals)。没有手动删除或重写状态文件,只重置 JS 会话并重试,即得到:
{"initialized":true,"appCount":40,"windowCount":6}
{"windowEnumerationPassed":true,"windowCount":6}以上数字来自本次历史成功记录,仅证明初始化、应用枚举和窗口枚举恢复。本次没有进行完整的鼠标键盘端到端测试。 EOF 与并发状态刷新的关联只是推测,竞态根因未验证,因此工具不会自动删除或重写该状态文件。
3. 通用排查流程:先只读诊断,再决定是否修复
以下示例不内置特定账号、盘符或 SID。请在正常登录用户的 PowerShell 中运行,避免误用 agent 沙箱身份。
3.1 确认当前身份和管理员令牌
whoami
whoami /user
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
$principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)最后一行输出 True 才表示当前 PowerShell 令牌具有启用的管理员角色(窗口标题不是充分证据)。
几个注意事项:
如果输出账号是
CodexSandboxOffline,说明你在沙箱内,不要把它填入授权对象。如果使用另一个管理员账号完成 UAC 提权,应保留原先运行 Codex 的普通用户作为
TargetAccount。
3.3 检查目标目录的所有者与权限规则
$target = Read-Host '输入日志中的一个精确绝对目录'
Get-Item -LiteralPath $target -Force | Select-Object FullName, Attributes
$acl = Get-Acl -LiteralPath $target
$acl | Select-Object Owner, AreAccessRulesProtected
$acl.Access | Format-Table IdentityReference, FileSystemRights, AccessControlType, IsInherited, InheritanceFlags建议同时在"属性 → 安全 → 高级 → 有效访问"中,针对运行 Codex 的普通用户核验其更改权限能力。必要时请管理员检查组成员与 Deny 规则。配套工具会展示 ACL 和直接适用规则,但不替代完整的 Windows 有效权限计算器。
📋 路径注意事项: 粘贴路径时保留反斜杠。在本案例的聊天输出中,曾出现
inxvision-iot.git、fengin.codex这种丢失反斜杠的文本——实际核验发现这两个错误路径均不存在,实际修复目标是正确的。PowerShell 示例使用单引号或变量配合-LiteralPath。不要把 JSON 的双反斜杠或 Markdown 显示文本未经核验就当作文件路径。
4. 理解 WDAC:什么是"更改权限"权限
WDAC 是修改 DACL 的权限,在 .NET 中对应 ChangePermissions,掩码为 0x40000。容易混淆的几个概念:
icacls /grant 不加 :r 时为增加权限(不替换原有),/T 才是递归遍历子项。参见 Microsoft:icacls。
WDAC 的风险
WDAC 虽然比 FullControl 的直接权限集合小,但绝非"无害的小权限"——拥有 WDAC 的用户可以重新配置目录的访问规则,包括给自己或其他身份加权。因此必须由管理员确认:这个具体用户确实可以管理这个具体目录的权限。
配套工具的修改边界
本工具固定添加一条 Allow WDAC,且没有 ContainerInherit/ObjectInherit 标志(仅作用于目录本身)。它不会:
修改所有者或继承开关
删除 Deny 规则
添加 FullControl
关闭沙箱、防火墙、UAC 或安全软件
修改模型、账号或订阅能力
实现上,工具通过锁定目录句柄写入 DACL,并在写前/写后比对。写句柄使用 Windows 的 MAXIMUM_ALLOWED 打开方式,按微软说明避免 SetSecurityInfo 向子项传播已有的可继承 ACE(这不是给账号授予"最大权限")。只传入 DACL 标志,原所有者和其他部分保持不变。参见 Microsoft:SetSecurityInfo。
⚠️ 目标及所有祖先目录均需能被校验和锁定。联接、符号链接、挂载点、短路径别名、网络映射等情况会被拒绝。某些合法但特殊的环境也可能被保守拒绝,应交管理员判断。
5. 使用配套工具
5.1 解压并审阅
将分享包解压到可信的普通目录,先阅读 README 和脚本。脚本以 UTF-8 BOM 保存,便于 Windows PowerShell 5.1 正确读取中文。
本工具不修改任何作用域的 ExecutionPolicy,也不使用 Bypass。如果执行策略、AllSigned、组策略、应用控制或 Constrained Language 阻止运行,请停止并让管理员按组织流程审阅和签名。双击窗口闪退时,可从已有 PowerShell 打开入口查看错误。
5.2 命令行预览:明确输入,先做 WhatIf
切换到解压目录,填写以下变量(不要把示例改成扫描所有用户目录):
$tool = Join-Path (Get-Location).Path 'Repair-CodexComputerUseAcl.ps1'
$targetUser = Read-Host '输入运行 Codex 的普通用户:域\用户名 或 SID'
$targets = @(Read-Host '输入一个已核实的精确绝对目录')
$backupParent = Read-Host '输入已创建的专用备份父目录绝对路径'
& $tool
& $tool -Mode Inspect -TargetPaths $targets -TargetAccount $targetUser
& $tool -Mode DryRun -TargetPaths $targets -TargetAccount $targetUser
& $tool -Mode Repair -TargetPaths $targets -TargetAccount $targetUser -BackupDirectory $backupParent -WhatIf各模式说明:
无参数: 只显示帮助信息,不扫描目录。
Inspect: 只读查看目标路径、所有者和 DACL。
DryRun / -WhatIf: 计算修复计划但不执行,不创建备份、不写 ACL。预览会显示目标、所有者 SID、当前 DACL 和"是否需要添加 WDAC"。如果显示 False,说明可能已有直接适用的 WDAC,不应强制追加。
多个目标应写成 PowerShell 字符串数组通过 -TargetPaths 传入。以下输入会被拒绝:通配符、相对路径、磁盘根、用户根、重复目录、互相嵌套的目录。备份父目录不得位于目标内部或作为目标的祖先,且须预先存在。
5.3 管理员执行修复
准备工作:
关闭或暂停可能修改同一 ACL 的任务。
建议暂时退出正在持续刷新沙箱状态的 Codex(不要强制结束有未保存工作的应用)。
通过开始菜单或 Windows Terminal 打开"以管理员身份运行"的 PowerShell。
核验管理员令牌(见 3.1 节),重新设置上一步的变量。
💡 目录句柄可以防止重命名和路径替换,但不能阻止另一个有权限的进程修改 DACL。写前后比较不是原子事务,应在没有其他权限写入者的时段操作。
执行修复:
& $tool -Mode Repair -TargetPaths $targets -TargetAccount $targetUser -BackupDirectory $backupParent -Confirm
$LASTEXITCODE确认前会再次显示明确的修复对象。只有全部目标的原始描述符和元数据写入唯一备份集并成功回读后,才会执行第一笔修改。预期输出:
全部目标已备份:<专用备份父目录>\codex-acl-<UTC时间>-<随机ID>
请另外保存清单 SHA256:<64位哈希>
成功:<精确目标目录>
完成 ... 个目录。🔑 务必将备份目录路径和 manifest.json 的 SHA256 另存到可信位置。
receipt.json仅方便核对——同目录的文件和哈希可以一起被篡改,不能当作数字签名。不要把备份集加入公开分享包。
关于双击入口 Start-Repair.cmd: 入口先在普通窗口采集目标并预览。只有输入 REPAIR 后才请求 UAC,用户手动批准后,管理员窗口会重新预览并再次要求输入 REPAIR 才开始写入。使用不同管理员账号提权时,原先选定的普通用户仍是授权对象。取消 UAC 或取消输入即停止。
5.4 失败时的处理原则
遇到 error 5、特殊 ACL、Deny 冲突、目录身份改变、快照变化、备份写入失败或权限策略拦截时,立即停止,不要试图扩大权限范围。具体来说:
不要补上
/T、/reset、takeown不要删除 Deny 规则
不要改成给 Everyone 或 CodexSandboxOffline 授权
退出码 6 表示已经尝试过写 ACL:部分目标可能成功,最后一个目标的状态也可能不确定。保留全部 attempt-*.json、result-*.json 和清单,按下一节检查或还原。工具不会在异常后自动反向覆盖,以免将随后产生的保护规则删除。
6. 备份与还原
6.1 工具备份机制
每次有实际改动的 Repair 都使用新的唯一目录,不覆盖旧备份集。清单中保存的信息包括:版本、时间、机器标识、普通用户 SID/名称、每个规范化目标路径、卷/目录文件 ID 与创建时间、原所有者 SID、原始和预期安全描述符及哈希。
需要注意:
这里只备份 Owner/Group/DACL 元数据,不是数据文件备份,也不是 SACL 审计策略备份。
写入仅触及 DACL。
每次写入前保存 attempt,成功并回读后保存 result。即使进程中断,也可发现某项"可能已尝试"。
清单不会因为结果变化而改写。备份文件内容是数据,工具不从备份中执行 PowerShell。
6.2 从工具备份还原
Restore 不会自动选择"最新备份"。使用管理员 PowerShell,手动指定与原修复一致的用户和全部目标集合,先预览再执行:
$backupSet = Read-Host '输入要还原的那个完整备份集目录'
$savedHash = Read-Host '输入修复时另存的 manifest.json SHA256'
& $tool -Mode Restore -TargetPaths $targets -TargetAccount $targetUser -RestoreFrom $backupSet -ExpectedManifestSha256 $savedHash -WhatIf
& $tool -Mode Restore -TargetPaths $targets -TargetAccount $targetUser -RestoreFrom $backupSet -ExpectedManifestSha256 $savedHash -Confirm工具会核对:外部哈希、条目哈希、版本、机器、SID、路径映射、目录身份和所有者,还会重新计算"原 DACL + WDAC"是否确实等于预期 DACL。当前 ACL 必须仍等于工具预期结果或原始结果,已还原的目标会跳过。
⚠️ 关于 Codex 后续新增的规则: 如果 Codex 已成功刷新并新增了 Deny/ReadAndExecute 等规则,完整 DACL 很可能已发生变化。此时 Restore 会拒绝覆盖——这是正常的保护机制。应请管理员对比新旧规则,决定是否需要单独撤销当时新增的用户权限。不要通过重算哈希或编辑 manifest 来绕过检查。
6.3 历史 icacls 备份是另一种格式
本案例人工修复前的 git.acl、pcmanager.acl 是 icacls /save 格式,不能交给本工具的 Restore。只在管理员已审阅备份映射与当前 DACL、确认不会丢掉后续保护时,才按原保存时的相对路径基准使用 icacls /restore。
以下是单目标人工备份的通用写法(仅供有经验的管理员参考,不建议用来绕过工具验证):
$parent = Split-Path -LiteralPath $target
$leaf = [IO.Path]::GetFileName($target.TrimEnd('\'))
$aclBackupFile = Read-Host '输入新的备份文件绝对路径(必须不存在)'
if (Test-Path -LiteralPath $aclBackupFile) { throw '拒绝覆盖已有备份' }
Push-Location -LiteralPath $parent
try {
& icacls.exe $leaf /save $aclBackupFile
if ($LASTEXITCODE -ne 0) { throw '备份失败;停止,不授权' }
} finally { Pop-Location }还原时使用保存基准的父目录(不是凭猜测拼路径):
# 先人工核对备份文件里记录的相对路径,确认没有后续 ACL 变更需保留。
& icacls.exe $parent /restore $aclBackupFile
if ($LASTEXITCODE -ne 0) { throw '还原失败;停止并联系管理员' }如果有多个目标,必须所有目标备份成功后才能开始授权,不能边备份边修复。分享包不包含本案例的真实备份或真实 SID 清单。
7. 修复后的分层验收
按以下顺序逐步验证,每一步通过后再进行下一步:
沙箱基本功能: 在 Codex 中执行一个普通沙箱的只读命令(如
whoami)。不要用沙箱外命令成功来代替。日志确认: 对齐本次时间查看日志,确认
setup refresh的errors=[],且原 error 5 不再出现。历史旧错误仍留在日志中是正常的。ACL 核验: 只读查看目标目录 ACL:普通用户获得的权限仅作用于目录本身,所有者和继承未被人工改变,已有 Deny 保留。
Computer Use 初始化: 请 Codex 重新初始化并枚举应用/窗口。注意
node_repl/sky是工具运行环境中的接口,不是在普通 PowerShell 直接输入的命令。EOF 问题处理: 若再出现 EOF,先查对应的新日志。状态恢复后重置 JS 会话重试;持续复现时停止并收集相关时间段信息。不要自动删除状态文件。
GUI 操作验证(可选): 如业务需要,另行授权一个无副作用的鼠标/键盘操作并验证。只有完成此项才能报告完整 GUI 操作验收。
官方说明 Windows Computer Use 在活动桌面上工作,目标应用应可见。应用授权、系统权限、文件沙箱审批是不同层次,枚举成功不能替代目标应用的操作权限。参见 OpenAI:Computer Use。
8. 本次排查中的常见误区
关于插件源: 历史排查核对过 Computer Use 的用户目录源和缓存各 6 个文件,加密文件数均为 0。本次教程制作又核对其缓存为 6 文件、0 加密,配置 enabled 为 true。没有重装插件、修改 WindowsApps 或安装第三方 fast-patch 技能。第三方页面本次未能重新访问,相关背景只作为历史排查记录,不作为当前官方说明,也不提供执行其脚本的建议。
9. 分享包内容与参考资料
分享包只含教程、README、主工具、双击入口、测试驱动、验证记录及文件校验清单。不包含完整用户配置、日志全文、状态文件、原 ACL 备份、测试夹具、密码或密钥。
Codex-Computer-Use-ACL-Guide-v1.0.0.zip
官方文档(制作日核对,入口和产品名可能随版本变化):
OpenAI:Windows sandbox — 原生沙箱模式与排查范围
OpenAI:Computer Use — 插件、Windows 活动桌面和授权
Microsoft:icacls — WDAC、save、restore 和继承选项
Microsoft:SetSecurityInfo — 按句柄设置 DACL,以及 MAXIMUM_ALLOWED 与子项传播的说明
配套工具采用保守的拒绝策略:对于它无法确认的路径、身份或 ACL,宁可停止并提交精确证据,也不继续扩大授权范围。