Repository navigation
Windows 沙箱 workspace-write 档:任何子进程启动即 0xC0000142(DLL 初始化失败) #9083
Replies: 4 comments
|
|
#9086 这一条是我的讨论,也是关于windows沙箱导致权限受限的问题,这是同一个设计缺口:撤销常驻授权时,缺少清理路径。可以在我的帖子下面汇总,希望这对你有帮助。 |
补充一个决定性数据点:把默认 DACL 合并的 SID 换成 Everyone,workspace-write 全链恢复我不是原帖作者,但独立复现了同一现象,并补上了原二分矩阵里缺的那一格。 环境:Windows 11 22631 x64;本地管理员(SID 以 1. 对照矩阵(同一条链:
|
| 宿主可执行文件 | 模式 | 叶命令 | 结果 |
|---|---|---|---|
DeepSeek Harness.exe(Electron,node 模式) |
workspace-write | cmd / pwsh / node | ❌ 3221225794 |
DeepSeek Harness.exe |
workspace-write | wscript.exe / pythonw.exe(GUI 子系统) | ✅ 0 |
DeepSeek Harness.exe |
read-only | cmd / pwsh | ✅ 0 |
node.exe |
workspace-write | cmd / pwsh | ✅ 0 |
两点值得注意:
- 失败与叶命令的语言无关,与子系统类型有关:
python.exe(控制台子系统)同样崩,pythonw.exe(GUI 子系统)正常 → 换 Python 并不能绕开; - 同一台机器、同一份代码,宿主从
DeepSeek Harness.exe换成node.exe即正常。而windowsAclRunnerInvocation()用的正是process.execPath,桌面版下就是 Electron 二进制。
2. 原帖矩阵缺的那一格
原帖测过「不做 TokenDefaultDacl 合并 → 仍崩」,但没测「换一个 SID 去合并」。我用 asar 提取副本(未改动已安装的 DSH)逐格验证:
index.ts:304 合并所用的 SID |
Electron 宿主 + workspace-write |
|---|---|
现状 tempWriteSidPtr ?? writeSidPtr ?? worldSid(workspace-write 取到 temp 能力 SID) |
❌ 3221225794 |
改为 worldSid(Everyone) |
✅ 0 |
| 整段合并不做 | ❌(与原帖一致) |
并在完整生产链上复验(subprocess-local/runner 以 IPC + Job 启动 sandbox-windows-acl/runner,后者建受限令牌后再起 pwsh):{"type":"target-exit","exitCode":0}。
这条也解释了原帖其余各格为何仍崩:那些改法都没有让「新建对象自身的 DACL」里出现一个在该模式下真正生效的保活 SID——而 packages/sandbox/sandbox-windows-acl/README.md:102 恰好写明 keep-alive 组(logon SID + Everyone)缺失就是 0xC0000142 的成因。index.ts:296-303 的注释显示作者是刻意选 temp 能力 SID(避免把工作区能力泄露进临时树),所以这里可能需要在「不泄露能力 SID」与「保活」之间取一个不含能力 SID 的保活 SID。
3. 一个尚未解释、但可能有用的相关性
目前两例报告(原帖与本机)都是已提权的 RID-500 本地管理员。本机这类令牌的默认 DACL 实测为 Administrators(GENERIC_ALL) + SYSTEM(GENERIC_ALL) + logon SID(READ|EXECUTE),不含 Everyone、不含用户 SID;普通(过滤令牌)账户通常为 用户 SID + SYSTEM。这可能正是上游自测(普通账户)命不中的原因,建议在非提权账户上对拍一次以确认。
4. 一个反直觉的补充观察
AllocConsole() 给 Electron 宿主显式补一个控制台后,workspace-write 仍崩;而 GUI 子系统子进程(wscript / pythonw)却能存活。也就是说「宿主无控制台」不足以单独解释,但「宿主无控制台 × 控制台子系统子进程 × workspace-write」是稳定判别式,或许能帮定位到具体是哪一步 DLL 初始化被拒。
5. 建议
setTokenDefaultDaclGrant的合并 SID 改为一个保活组的 SID(Everyone 已验证有效),或至少优先验证该路径;packages/sandbox/sandbox-windows-acl/tests/control.spec.ts现有 "runs without a visible console" 用例,其 runner 是由带控制台、且为 node 的测试进程启动的;建议补「宿主本身无控制台」与「宿主为 Electron 二进制」两个维度;- 沙箱失败时把受限令牌构成(受限 SID 列表 SDDL、完整性级别、flags)写进日志,这类主机一行日志即可识别;
- 与 [Bug] workspace-write 沙箱拦掉 pwsh 7 启动,报 0xC0000135 (3221225794),工作区内终端不可用 #9134 合并处理:那条报的是同一现象(其
3221225794即0xC0000142,不是0xC0000135)。
复现脚本、逐格日志与单变量补丁可随时提供(补丁仅作用于 asar 提取副本,安装版未改动)。
追加:不依赖任何外部产物的最小复现(用已安装的 app 即可),以及一个保留原设计意图的修法上一条我用的是 asar 提取副本。下面这条不需要抽取、不需要额外工具,直接用已安装的桌面版就能复现( $exe = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\DeepSeek Harness.exe"
$runner = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\app.asar\dsh\node_modules\@deepseek-ai\dsh-sandbox-windows-acl\lib\runner.js"
$env:ELECTRON_RUN_AS_NODE = "1"
$ws = "$env:TEMP\dsh-repro\ws"; $tmp = "$env:TEMP\dsh-repro\tmp"
New-Item -ItemType Directory -Force -Path $ws, $tmp | Out-Null
& $exe $runner --workspace $ws --temp $tmp --mode workspace-write -- cmd.exe /d /s /c "exit 0" # => -1073741502 (0xC0000142)
& $exe $runner --workspace $ws --temp $tmp --mode read-only -- cmd.exe /d /s /c "exit 0" # => 0本机结果: 叶子命令的「子系统类型」是关键变量(同一宿主、同一模式、同一 runner):
⇒ 所以「把 shell 换成 Python」并不能绕开: 关于修法:我上一条给的是 - setTokenDefaultDaclGrant(api, restrictedToken, this.tempWriteSidPtr ?? this.writeSidPtr ?? worldSid)
+ setTokenDefaultDaclGrant(api, restrictedToken, logonSid)需要说明的是:我只端到端验证了 另:本环境的 GitHub 凭据没有 gist 权限,外部产物无法托管,因此复现脚本以内联形式放在这里。 |
Uh oh!
There was an error while loading. Please reload this page.
现象:Windows 沙箱(@deepseek-ai/dsh-sandbox-windows-acl)的 workspace-write 档在本机完全不可用。
它启动的任何子进程都会在 DLL 初始化阶段死亡,退出码 0xC0000142(STATUS_DLL_INIT_FAILED)。
read-only 档正常。故障可在 DSH 之外、用 DSH 自己的 runner 稳定复现。
环境:Windows 11 build 26100;PowerShell 7.6.6;本地管理员(S-1-5-21-224436101-3469062899-2174611767-500,已提权);
会话模式 workspace-write。
复现:"DeepSeek Harness.exe" /dsh/node_modules/@deepseek-ai/dsh-sandbox-windows-acl/lib/runner.js
--workspace --temp --mode workspace-write -- cmd /c exit 0
(ELECTRON_RUN_AS_NODE=1)
结果:read-only 全部 0x0;workspace-write 对 cmd、pwsh 7.6.6、powershell 5.1 全部 0xC0000142。
runner 没有打印 windows-acl-run 失败行、也不是退出码 127,说明令牌创建/能力 SID 授权/CreateProcessAsUserW
都成功了,是子进程起来之后死的。事件日志里没有对应 Application Error。
根因(已二分到唯一因素):该沙箱不是 AppContainer,而是 CreateRestrictedToken 的 WRITE_RESTRICTED
令牌(flags=13)+能力 SID(S-1-4-<sha256(工作区路径)>)。受限列表:read-only=[logonSid,Everyone];
workspace-write=[logonSid,Everyone,工作区能力SID,临时能力SID]。
单变量矩阵(在实验室副本里逐个打补丁,已安装的 DSH 未改动):
基线 cmd/pwsh 都 0xC0000142
去掉 Low IL 仍 0xC0000142
去掉 WRITE_RESTRICTED(13→5) 仍 0xC0000142
受限列表不放能力 SID 仍 0xC0000142
不做 TokenDefaultDacl 合并 仍 0xC0000142
不加能力 ACE 仍 0xC0000142
保留全部特权(flags=12) 仍 0xC0000142
对照组 read-only 0x0 正常
即:本机上只要能力 SID 进入受限列表,任何子进程必崩;与低完整性级别、WRITE_RESTRICTED 标志、
能力 ACE、默认 DACL 合并均无关。去掉能力 SID 不算修复,因为那正是 workspace-write 的意义。
已排除:ACL 损坏(随包技能判定 NOT_THIS_CLASS,granted=0,无需修复);
AppContainer 相关注册表键缺失(本机确实缺 HKLM...\AppContainer 及 Storage/Mappings,但该沙箱不用
AppContainer,与本例无关,值得单独查);可执行文件/路径问题;安全软件干扰。
影响:workspace-write 是默认档,且 Windows 上是单候选链、无回退,本机一旦启用沙箱 shell 就完全不可用。
本机临时处置:禁用 pwsh-sandbox、插入 @deepseek-ai/dsh-pwsh-local,恢复可用,代价是 shell 失去文件围栏。
建议:1) Windows 上提供回退档(例如不加能力 SID、仅 Job Object/Low IL 的围栏),避免主档一坏就没有 shell;
2) 子进程在受限令牌下以 0xC0000142 死亡时,作为沙箱失败上报,并带上令牌构成(受限列表 SDDL、
完整性级别、flags),这样这类主机一行日志就能识别。
附件(本机生成、可复现):sandbox-probe.js(直接驱动 DSH runner 复现上表)、acl-report-*.jsonl
(随包 ACL 技能完整记录)、exp2-run.js/exp3-run.js/extract-asar.js/copy-from-asar.js(二分实验台与
asar 提取工具)、RECOVERY-CONTEXT.md / FINAL-STATE.md(完整取证与被否假设)。需要可随时提供。
可随时配合复现:Windows 11 26100、本地管理员。
All reactions