Repository navigation
Windows: confined commands die with 0xC0000142 because the sandbox runner is the Electron (GUI-subsystem) binary #10066
Replies: 5 comments
Follow-up: the workaround is verified on the desktop appApplied the After a restart, with the session back in Confined execution works again and the write boundary is still enforced (the escape write was denied), so this does not silently degrade to unconfined execution. Side effect:
|
|
Your root cause holds up at source, and your follow-up corrects three things — one of which is a real defect I do not think you have spotted the full shape of. Everything below is checked against The root cause: confirmed, and the code comment argues against itself
// :568 (docstring)
// The prefix stays `[node, runner, ...]` — a future native-exe runner keeps
// the same argv contract and only swaps these entries.
if (existsSync(builtEntry)) return [process.execPath, builtEntry] // :575
return [process.execPath, '--import', `data:text/javascript,…`, sourceEntry] // :579The docstring says the prefix is I would add one piece of evidence in your favour that the module does not state anywhere: Your two extra rows are the sharpest part of the report, and the source agrees with the mechanism:
Your three follow-ups, one at a time(a) The diagnosis skill disappearing — documented and test-pinned, but your case falsifies the premise it rests on. This is not a regression. The gate is // An operator-supplied runner does not use the ACL backend. The registry
// remains optional and may be mounted after this provider.
if (process.platform === 'win32' && this.runnerCommand === undefined) {
ctx.inject(['skills'], (skillsCtx) => { registerAclDiagnosisSkill(skillsCtx) })
}It is documented twice — But the comment's premise is "an operator-supplied runner does not use the ACL backend", and your workaround is the counter-example: a custom runner that is the ACL backend, only hosted in (b)
(c) The denial dialect — this one is a real defect, and it is worse than you described.
const DENIAL_SIGNATURES = {
bwrap: ['read-only file system'],
landlock: ['permission denied'],
seatbelt: ['operation not permitted'],
// pwsh/.NET: "Access to the path '...' is denied."; cmd: "Access is denied.";
// Node EACCES: "permission denied"; EPERM: "operation not permitted".
'windows-acl': ['access is denied', 'access to the path', 'permission denied', 'operation not permitted'], // :213
runnerCommand: ['read-only file system', 'permission denied'], // :214
}The Windows rung's four signatures were enumerated deliberately, with the dialect of each source named in the comment above them. The There is a fourth asymmetry you did not name, in the same branch. Suggested fixYour option 1 ( A note on toolingThis failure family is what |
|
Confirming on a different environment: Windows 10 22H2 (19045), dsh-desktop 0.12.0, running elevated (Administrator, High mandatory level). Every confined command dies identically: exit code 3221225794, no stdout, no stderr — Two data points that may widen the report:
The |
|
The bash stack has the same defect, but it fails silently ( Environment: DSH Desktop 2.0.18, harness 1. ReproductionProfile - id: pwsh-sandbox
disabled: true
- id: bash-sandbox
disabled: false
- id: tool-pwsh
disabled: true
- id: tool-bash
disabled: falseThat is the complete recipe from
2. Root cause: same argv composition, different failure mode
Measured directly on the same machine: # un-adapted argv (what the bash stack produces)
".../DSH Desktop.exe" runner.js --workspace <ws> --temp <tmp> --mode workspace-write -- bash -c 'echo hi; exit 42'
# → no output, exit 0, 446 ms
# identical argv, only ELECTRON_RUN_AS_NODE=1 added
ELECTRON_RUN_AS_NODE=1 ".../DSH Desktop.exe" runner.js ... -- bash -c 'echo hi; exit 42'
# → hi, exit 42So 3. Second, independent gap:
|
补充验证:
|
| mode | 父进程控制台 | 结果 |
|---|---|---|
read-only |
有 | exit 7,stdout HELLO |
read-only |
无 | exit 7,stdout HELLO |
workspace-write |
有 | exit 7,stdout HELLO |
workspace-write |
无 | exit 3221225794 (0xC0000142),stdout 空 |
结论
失败要求同时满足两个条件:受限于 workspace-write 的 restricting 列表,且父进程无控制台。
read-only的 restricting 列表不含能力写 SID,故无控制台时仍可正常启动 —— 这为 Windows: confined commands die with 0xC0000142 because the sandbox runner is the Electron (GUI-subsystem) binary #10066 中「read-only有时能跑」给出可复现的判定条件。workspace-write在无控制台宿主下稳定失败,与 [Bug] 桌面版 0.2.1-rc.2 / Windows:workspace-write 下所有 shell 命令 0xC0000142(独立复现) #10362 现象一致。
对 #10066 修复建议的补充数据
在无控制台父进程下,对受限子进程的启动标志做了穷举,验证「子进程自带控制台」是否可行:
| 启动方式 | 结果 |
|---|---|
creationFlags = 0 |
❌ 0xC0000142 |
creationFlags = CREATE_NO_WINDOW (0x08000000) |
❌ 0xC0000142 |
creationFlags = CREATE_NEW_CONSOLE (0x00000010) |
❌ 0xC0000142 |
父进程先 AllocConsole(),再以 creationFlags = 0 启动 |
✅ exit 7 |
即:无法通过子进程侧的控制台标志绕过,必须在 runner 侧先取得控制台(或如 #10066 建议改用控制台子系统的 node.exe)。这与 #10066 的结论方向一致,此处补充了「子进程侧两种标志均无效」的实测依据。
环境(已脱敏)
| 项 | 值 |
|---|---|
| DSH | 0.2.1.0 |
| OS | Windows 11 x64,10.0.22631 |
| PowerShell | 7.6.6(C:\Program Files\PowerShell\7\pwsh.exe) |
| 宿主 | 桌面版,进程树内无控制台(AttachConsole 返回 ERROR_INVALID_HANDLE) |
| 账户 | 内置管理员账户,High 完整性(UAC 关闭) |
| 会话策略 | workspace-write(失败)/ danger-full-access(正常) |
另外一点(与 #10066 的 read-only 描述相关)
若按 #10066 修复方案 2 改用随包 node.exe 作为 runner 宿主,需要注意它在 app.asar.unpacked 下的路径与 asar 边界问题——该 caveat 在 #10066 中已有说明,此处不重复。
本数据来自一次独立复现,不依赖 DSH 进程内状态;脚本未提交(仅在本地临时目录运行)。
Uh oh!
There was an error while loading. Please reload this page.
Summary
On the Windows desktop app (
0.2.1-rc.2, Windows 11 26200, AMD64), every command run while the session is inworkspace-writefails immediately:No stdout, no stderr.
cmd /c echo okbehaves the same, and the PTY terminal reportsPTY shell exited during startup. Full access (danger-full-access) works without issues.Root cause
@deepseek-ai/dsh-sandbox-localbuilds the Windows runner argv as:In the desktop app,
process.execPathisDeepSeek Harness.exe— an Electron GUI-subsystem binary. A GUI-subsystem process is never attached to a console.The ACL runner then starts the confined target (
pwsh,cmd,node) withCreateProcessAsUserW. Since the parent owns no console, the console-subsystem child has to create a fresh console, and theWRITE_RESTRICTED+ Low-integrity token cannot do that — the child dies during DLL initialization withSTATUS_DLL_INIT_FAILED.This also explains the neighbouring observations:
read-onlysometimes works: its restricting list carries no write SIDs, so the console-creation path still passes;notepad) always work, because they never need a console.Reproduction (same runner, outside the app)
The chain
host → subprocess runner → windows-acl runner → targetwas reproduced directly, only varyingprocess.execPath:node.exe(console subsystem)000xC00001420AllocConsole()before spawn0The last row is the decisive one: giving the runner a console fixes it immediately, and so does swapping the runner to the bundled
node.exe.Suggested fix (either is enough)
@deepseek-ai/dsh-sandbox-windows-acl/lib/runner.js, before spawning: ifGetConsoleWindow()is NULL, callAllocConsole()(optionally hiding the window withShowWindow(..., SW_HIDE)). Verified to fix the failure locally.process.execPathas the runner program when it resolves to a GUI-subsystem executable; use the bundled console-subsystem node (resources/runtime/primary-runtime/dependencies/node/bin/node.exe). Note that plainnode.execannot readapp.asar, so the runner entry has to come from an unpacked copy orapp.asar.unpacked.Workaround (user side, no patching)
Override
sandbox-localin the profile patch layer and route the runner throughnode.exe:A shim is required because a custom
runnerCommandreceives the bwrap profile dialect (--ro-bind / / --dev /dev ... --bind <ws> <ws> -- <argv>), while the Windows ACL runner expects--workspace/--temp/--mode -- <argv>. The shim translates the former into the latter and launches the ACL runner undernode.exe.Two caveats for this path:
enforcementis reported asfullfor custom runners, and the denial dialect (DENIAL_SIGNATURES.runnerCommand=read-only file system/permission denied) does not match the Windows denial text (Access is denied), so sandbox denials render as plain non-zero exits.中文摘要
桌面版(Electron)会把沙箱 runner 用
process.execPath启动,也就是 GUI 子系统的DeepSeek Harness.exe。GUI 进程没有控制台,于是受限令牌下的控制台子进程(pwsh/cmd/node)必须新建控制台,而 Low 完整性 +WRITE_RESTRICTED令牌不允许,最终以0xC0000142在 DLL 初始化阶段死亡。修复只需二选一:runner 启动前AllocConsole(),或改用随包的node.exe作为 runner 宿主。All reactions