ChatGPTClaudeGrok / X / CursorGemini

DeepSeek Harness workspace-write 报 0xC0000142:默认 DACL 怎么排查

故障排查发布于 2026-10-30作者: DeepSeek Plugin 插件市场
DeepSeek HarnessDSHWindows0xC0000142workspace-writeDACL受限令牌沙箱
DeepSeek Harness 在 Windows 上只有 workspace-write 沙箱失败、read-only 正常,所有 shell 都返回 0xC0000142?根因是受限令牌的默认 DACL 指名了派生能力 SID。本文用单变量对照实验带你确认,并说明为什么不建议直接换成 world SID。

DeepSeek Harness 在 Windows 上切到 workspace-write 后,所有 shell 子进程都返回 0xC0000142,而 read-only 下同样的命令能跑——这类「只在 workspace-write 挂」的案例,根因通常在受限令牌的默认 DACL:workspace-write 把派生能力 SID 写进了 TokenDefaultDacl,read-only 写的是 world SID。 难点不在结论,而在证据:这两种模式同时改了两个部位,直接对比根本分不清是 restricting 列表还是默认 DACL。社区最后是靠「只覆盖默认 DACL」的单变量实验才钉死的(#11223、#11448)。

DeepSeek Harness 先做减法:把「两处同时变」拆成单变量

read-only 与 workspace-write 的差异不只在默认 DACL,还在 restricting SID 列表;只要两处一起变,任何对比都只能得到「workspace-write 有问题」,无法归因到具体字段。

先复现一个最小对照:

  1. 新建一个空目录作为工作区,里面只放一个 echo 1 的测试脚本。
  2. 切到 read-only,执行 echo 1,确认能正常返回。
  3. 切到 workspace-write,执行同一条命令,确认返回 0xC0000142 且无输出。
  4. 记录两次的完整退出码与时间,不要只看界面上的「失败」两个字。

接下来做单变量实验。核心思路是:让 DSH 按原样构造令牌,只在构造完成后覆盖 TokenDefaultDacl,其他字段一律不动。

  1. 用管理员权限打开一个调试终端,启动 DSH 并复现失败。
  2. 找到失败子进程的父进程,确认它使用的受限令牌。
  3. 只把该令牌的 TokenDefaultDacl 换成 S-1-5-11(Authenticated Users)或当前登录的 logon SID。
  4. 保持 restricting SID 列表、完整性级别、会话 ID 完全不变,再启动子进程。
  5. 如果这次能起来,根因就锁定在默认 DACL;如果仍然 0xC0000142,再回去查 restricting 列表或控制台。

这一步的价值在于排除法:只改一处、只观察一个结果,结论才站得住。社区最初也有「System32 上没有能力 SID 的读 ACE」的推测,后来正是用这个实验撤回了,因为真正起决定作用的是默认 DACL。

DSH插件 根因:默认 DACL 指名了派生能力 SID

sandbox-windows-acl/src/index.ts:304 的 setTokenDefaultDaclGrant(api, restrictedToken, this.tempWriteSidPtr ?? this.writeSidPtr ?? worldSid) 决定了默认 DACL 用哪个 SID;workspace-write 下这里落到派生能力 SID,read-only 下落 world SID。

把调用链展开:

  1. 进入 workspace-write,DSH 需要临时写权限,于是准备 tempWriteSid / writeSid。
  2. 构造受限令牌后,把默认 DACL 授权给这个能力 SID。
  3. 子进程创建对象时,默认继承这个 DACL。
  4. 但子进程在更早的 DLL 初始化阶段就要读取系统路径;能力 SID 在这些路径上没有读 ACE,初始化直接失败。
  5. 失败表现为 0xC0000142,因为进程还没走到执行命令的那一步。

代码上方的注释(index.ts:301-303)写明了这么做的目的:一个会话临时目录里创建的对象,不应该获得共享工作区的能力。 也就是说,能力 SID 不是写错了,而是有意为之;问题在于它同时被用在了「进程启动所需的默认 DACL」上,范围过窄,导致子进程连初始化都过不了。

DeepSeek Harness 为什么不能直接换成 world SID

把默认 DACL 换成 S-1-5-11 或 Everyone 确实能让进程起来,但等于拆掉了「临时目录对象不继承共享工作区能力」这层隔离;更合适的修法是把 logon SID 与能力 SID 并列,而不是替换。

三种候选的取舍可以这样看:

候选 SID子进程能否启动隔离强度结论
派生能力 SID(现状)不能最强需要补一个更宽的 SID
S-1-5-11 / Everyone能最弱,跨会话可见只适合验证,不适合作为修复
当前登录 logon SID能较强,跨会话仍隔离推荐的修复方向

社区的建议是:在默认 DACL 里同时保留能力 SID 和 logon SID。这样临时目录对象仍然拿不到共享工作区能力,但子进程启动所需的基础读权限有了。findLogonSid 在同一包的 token.ts 里已经存在,index.ts:55 也已经导入,改动面并不大。

DeepSeek插件 用户侧能做什么:没有开关,只能换宿主或等修复

目前没有面向用户的配置项能改默认 DACL;能立刻恢复工作的只有换宿主或临时放开沙箱,保留 workspace-write 只能等核心修。

按代价从低到高:

  1. 改用 dsh web:Node 宿主不经过桌面端这条受限令牌链,workspace-write 下的命令通常能正常执行;代价是你要接受浏览器访问的工作方式。
  2. 临时切 danger-full-access:命令能跑,但沙箱隔离没了,只建议在可信项目里短期用。
  3. 换一台没有该问题的机器/账户:如果只是临时交付,可以把任务挪到 Linux 或 macOS,绕开 Windows 令牌差异。
  4. 等核心修复:关注默认 DACL 构造是否改为「能力 SID + logon SID」,不要指望 rc 线的小版本会带上。

如果你有源码环境,也可以自己打补丁:在 setTokenDefaultDaclGrant 调用处追加 logon SID,然后跑一遍 echo 1、文件写入、跨会话访问三组验证。只验证「命令能跑」不够,还要确认跨会话隔离没被破坏。

DeepSeek Harness 和另外两类 0xC0000142 的分界

默认 DACL 这条的判据是「只有 workspace-write 挂、read-only 正常、账户不是内置 Administrator」;三条都满足再往下查,不要一上来就改令牌。

判据默认 DACL内置 Administrator控制台问题
账户 SID任意以 -500 结尾任意
read-only 是否正常正常通常也挂通常也挂
dsh web 是否正常正常正常正常
关键证据只改默认 DACL 即恢复升级 alpha.2 即恢复不新建控制台即恢复

先把这三条判据跑完,再决定要不要动令牌。一次改多个变量,最后只会得到「好像都好了一点」的模糊结论。

DSH插件 注意事项:做实验时的四个坑

下面这些做法会加重问题或掩盖真因,先避开再谈修复。

  1. 不要在生产会话里直接改令牌。用独立的测试工作区和测试账户,避免把正在跑的任务一起弄挂。
  2. 不要只验证 echo 1。还要验证写文件、读系统路径、跨会话访问,确认修复没有把隔离一起拆掉。
  3. 不要把 S-1-5-11 当成最终方案。它只适合做单变量验证,范围太宽。
  4. 不要忽略版本差异。不同 rc 构建的 index.ts 行号可能变化,定位时以函数名 setTokenDefaultDaclGrant 为准,不要死记行号。

这类问题的麻烦之处在于「看起来像权限不足,实际上是令牌构造过窄」。先用单变量实验把根因钉死,再决定是换宿主、等修复,还是自己补 logon SID;不要在账户、ACL、控制台三个方向之间来回试。相关排查见 DeepSeek Harness Windows 子进程报 0xC0000142:受限令牌与宿主定位。

ChatGPTClaudeGrok / X / CursorGemini

常见问题

DeepSeek Harness 只有 workspace-write 下 shell 全报 0xC0000142,read-only 却正常,是什么原因?

优先怀疑是 DeepSeek Harness 受限令牌的默认 DACL:workspace-write 下 setTokenDefaultDaclGrant 用的是派生能力 SID,read-only 用的是 world SID。能力 SID 在部分系统路径上没有读 ACE,子进程在 DLL 初始化阶段就失败,统一返回 0xC0000142。

为什么不能直接把 DeepSeek Harness 的默认 DACL 改成 Everyone 或 Authenticated Users?

因为 DeepSeek Harness 的默认 DACL 作用是限制「本次会话临时目录里新建的对象」不要拿到共享工作区能力。换成 S-1-5-11(Authenticated Users)范围太宽,等于把这层隔离拆掉。更合理的做法是把同一登录的 logon SID 与能力 SID 并列加入,既让子进程能起来,又保留跨会话隔离。

在 DeepSeek Harness 中,怎么用单变量实验确认问题出在默认 DACL 而不是 restricting 列表?

read-only 与 workspace-write 在 DeepSeek Harness 里同时改了两处:restricting 列表和默认 DACL,直接对比无法归因。需要保持 restricting 列表不变,只覆盖令牌的 TokenDefaultDacl,把它换成 logon SID 或 S-1-5-11 再启动子进程;只有这一处变、进程能起来,才能把根因钉在默认 DACL 上。

普通用户现在能靠配置项绕过 DeepSeek Harness 的这个 0xC0000142 吗?

DeepSeek Harness 目前没有直接配置项能绕过这个 0xC0000142。可行的替代是改用 dsh web(Node 宿主,不走这条桌面令牌链),或临时切 danger-full-access。要保留 workspace-write,只能等核心修改默认 DACL 的构造方式,或在有源码的环境里自行打补丁。

同样是 workspace-write 下 0xC0000142,怎么排除 DeepSeek Harness 的内置 Administrator 和控制台问题?

先在 DeepSeek Harness 里看账户 SID 是否以 -500 结尾,排除 LUA_TOKEN;再看桌面端与 dsh web 是否表现不同,排除控制台创建标志;最后才做默认 DACL 的单变量覆盖。三步顺序不要颠倒,否则一次改多个变量,结果无法解释。

相关术语

TokenDefaultDacl
TokenDefaultDacl 是 Windows 访问令牌里的默认 DACL 字段,决定该令牌创建的对象的默认访问控制项。DeepSeek Harness 在 workspace-write 下把派生能力 SID 写进这里,用来阻止临时目录对象继承共享工作区能力。— https://github.com/deepseek-ai/deepseek-harness/discussions/11448
派生能力 SID
派生能力 SID 是 Windows 受限令牌中由 `CreateRestrictedToken` 生成的能力 SID(通常以 `S-1-4-` 开头),用于把访问权限收窄到特定能力集合。它不等同于用户或组 SID,在部分系统路径上没有读 ACE。— https://github.com/deepseek-ai/deepseek-harness/discussions/11223
logon SID
logon SID 是 Windows 登录会话 SID(`S-1-5-5-X-Y`),标识一次具体登录。它比 `Authenticated Users` 窄,又比派生能力 SID 更接近普通进程所需权限,因此常被用作默认 DACL 的最小修复候选。— https://github.com/deepseek-ai/deepseek-harness/discussions/11448
restricting SID 列表
restricting SID 列表是 `CreateRestrictedToken` 的 restricting SIDs 参数,定义受限令牌额外要求通过的访问检查。它与默认 DACL 是两个独立部位,排查时必须分开改动,否则无法判断是哪一处导致子进程失败。— https://github.com/deepseek-ai/deepseek-harness/discussions/11223

来源