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. 适用条件

以下四个条件同时满足,才适合按本文操作:

  1. Windows 原生 Codex 沙箱启动或刷新失败(Computer Use 的 Node 内核也可能在执行 JS 之前退出)。

  2. 最新且与失败时间对应的日志中出现 SetNamedSecurityInfoW failed ...: 5,明确指出某个目录无法添加 deny/read ACE。

  3. 该目录是本地普通目录,经核查所有者、DACL 和执行身份后,确认运行 Codex 的普通用户缺少修改该目录 DACL 的能力。

  4. 管理员同意为该用户授予目标目录的权限管理能力,并允许先备份再修改。

以下问题不在本文范围内: 插件未安装或被禁用、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 "能写文件"不等于"能改权限"

目标目录

修复前所有者

实际问题

D:\code\work\inxvision-iot\.git

AIBOOK\CodexSandboxOffline

普通用户 AIBOOK\fengin 有继承的 Modify 等权限,但缺少修改 DACL 的能力

C:\Users\fengin\PCManger

BUILTIN\Administrators

普通用户没有修改 DACL 的权限,沙箱读取规则添加失败

这里有两个常见误解需要澄清:

  • 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\fenginChangePermissions 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.gitfengin.codex 这种丢失反斜杠的文本——实际核验发现这两个错误路径均不存在,实际修复目标是正确的。PowerShell 示例使用单引号或变量配合 -LiteralPath。不要把 JSON 的双反斜杠或 Markdown 显示文本未经核验就当作文件路径。

4. 理解 WDAC:什么是"更改权限"权限

WDAC 是修改 DACL 的权限,在 .NET 中对应 ChangePermissions,掩码为 0x40000。容易混淆的几个概念:

缩写

含义

掩码

WDAC

修改 DACL(更改权限)

0x40000

WD

写数据/添加文件

0x02

WO

更改所有者

0x80000

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 管理员执行修复

准备工作:

  1. 关闭或暂停可能修改同一 ACL 的任务。

  2. 建议暂时退出正在持续刷新沙箱状态的 Codex(不要强制结束有未保存工作的应用)。

  3. 通过开始菜单或 Windows Terminal 打开"以管理员身份运行"的 PowerShell。

  4. 核验管理员令牌(见 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/resettakeown

  • 不要删除 Deny 规则

  • 不要改成给 Everyone 或 CodexSandboxOffline 授权

退出码 6 表示已经尝试过写 ACL:部分目标可能成功,最后一个目标的状态也可能不确定。保留全部 attempt-*.jsonresult-*.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.aclpcmanager.aclicacls /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. 修复后的分层验收

按以下顺序逐步验证,每一步通过后再进行下一步:

  1. 沙箱基本功能: 在 Codex 中执行一个普通沙箱的只读命令(如 whoami)。不要用沙箱外命令成功来代替。

  2. 日志确认: 对齐本次时间查看日志,确认 setup refresherrors=[],且原 error 5 不再出现。历史旧错误仍留在日志中是正常的。

  3. ACL 核验: 只读查看目标目录 ACL:普通用户获得的权限仅作用于目录本身,所有者和继承未被人工改变,已有 Deny 保留。

  4. Computer Use 初始化: 请 Codex 重新初始化并枚举应用/窗口。注意 node_repl/sky 是工具运行环境中的接口,不是在普通 PowerShell 直接输入的命令。

  5. EOF 问题处理: 若再出现 EOF,先查对应的新日志。状态恢复后重置 JS 会话重试;持续复现时停止并收集相关时间段信息。不要自动删除状态文件。

  6. GUI 操作验证(可选): 如业务需要,另行授权一个无副作用的鼠标/键盘操作并验证。只有完成此项才能报告完整 GUI 操作验收。

官方说明 Windows Computer Use 在活动桌面上工作,目标应用应可见。应用授权、系统权限、文件沙箱审批是不同层次,枚举成功不能替代目标应用的操作权限。参见 OpenAI:Computer Use

8. 本次排查中的常见误区

误区

实际情况

只看 sandbox.log

必须同时检查带日期的日志文件和 LastWriteTime

普通用户能改文件就能改 ACL

Modify 不含 WDAC

sandbox="elevated" 意味着 GUI 必须提权

它描述的是沙箱实现方式,GUI 令牌不是判据

桌面进程一定叫 Codex.exe

本案例包为 OpenAI.Codex_26.831.2377.0,桌面进程可叫 ChatGPT.exe,CLI 版本为 0.152.1

按教程一定能找到 Local 或 Set up 按钮

UI 与版本/状态有关,不能承诺固定按钮位置

插件重装可以解决一切初始化失败

本次 Computer Use 与 Chrome 插件均已 installed/enabled(版本 26.831.21537),问题出在沙箱 ACL 刷新

复制 WindowsApps 插件源即可修 error 5

当时对照的第三方指南处理的是源复制 os error 6000,与本次目录 DACL 的 error 5 不是同一故障

把授权对象改成 CodexSandboxOffline

会混淆桌面用户与沙箱安全边界,不能这样做

EOF 就删状态 JSON

本次文件自行恢复,未证明需要删除,也未验证竞态根因

初始化成功 = 鼠标键盘全部通过

本次验收范围止于初始化和枚举

关于插件源: 历史排查核对过 Computer Use 的用户目录源和缓存各 6 个文件,加密文件数均为 0。本次教程制作又核对其缓存为 6 文件、0 加密,配置 enabled 为 true。没有重装插件、修改 WindowsApps 或安装第三方 fast-patch 技能。第三方页面本次未能重新访问,相关背景只作为历史排查记录,不作为当前官方说明,也不提供执行其脚本的建议。

9. 分享包内容与参考资料

分享包只含教程、README、主工具、双击入口、测试驱动、验证记录及文件校验清单。不包含完整用户配置、日志全文、状态文件、原 ACL 备份、测试夹具、密码或密钥。
Codex-Computer-Use-ACL-Guide-v1.0.0.zip

官方文档(制作日核对,入口和产品名可能随版本变化):

配套工具采用保守的拒绝策略:对于它无法确认的路径、身份或 ACL,宁可停止并提交精确证据,也不继续扩大授权范围。

分享协议:  CC BY 4.0

©2026 AI全书. 保留部分权利

    备案号: 浙ICP备06043869号-8