Repository navigation
Windows workspace-write sandbox: every confined child dies with 0xC0000142 (root cause + verified patch) #9038
Xialibarenud
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Component:
packages/sandbox/sandbox-windows-acl(@deepseek-ai/dsh-sandbox-windows-acl)Host version:
@deepseek-ai/dsh@0.2.0-rc.2(Desktop profile, Web GUI)Platform: Windows 10 (10.0.19041), x64, Node 24.21.0, PowerShell 7.6.6
Severity: confined shell is completely unusable in the default (
workspace-write) modeSummary
On this host, every command run through the
pwshtool while the session file policy isworkspace-writefails with a bare[exit code: 3221225794](0xC0000142,STATUS_DLL_INIT_FAILED) — no stdout, no stderr, nowindows-acl-run:runner-failure signature.The same host, same session, same binary works fine in
read-only.Root cause is a single line in
AclSandbox.init(): the restricted token's default DACL isseeded with the capability write SID in
workspace-write, whileread-onlyfalls back toEveryone. On a host where the parent process token's default DACL lacksEveryone, the childcannot complete process/DLL initialization and dies before it can print anything. Adding
Everyonealongside the capability SID fixes it without weakening confinement.Reproduction
Bisection (one variable per step)
node.exe,workspace-writewindowsHide+ piped stdio--write-sid/--temp-write-sid)TMP/TEMPrewrite (3 variants)cmd.exe/node.exe/pwsh.exeprocess.execPath(Electron binary as node)read-onlylistEveryoneEveryoneboth seededRoot cause
AclSandbox.init()(lib/types-*.js):setTokenDefaultDaclGrantmerges one full-access ACE into the token's existing default DACL:read-only— no write SIDs exist, so it falls back toworldSid→ the default DACL keeps anEveryoneACE → works.workspace-write— it resolves to the capability SIDS-1-4-…→ the default DACL receivesonly that ACE and loses
Everyone→ the confined child fails DLL initialization andexits with
STATUS_DLL_INIT_FAILED.This is why the error looks like a file-permission problem but is not: the bundled
diagnose-windows-sandbox-aclrun reportsNOT_THIS_CLASS(fullWRITE_DAC/WRITE_OWNERon thewhole chain, zero foreign package SIDs). It is a token default, not a file ACL.
Suggested fix
setTokenDefaultDaclGrant(api, restrictedToken, this.tempWriteSidPtr ?? this.writeSidPtr ?? worldSid); +if (this.mode !== "read-only") setTokenDefaultDaclGrant(api, restrictedToken, worldSid);Keeps the capability SID and restores the
EveryoneACE thatread-onlyalready gets. Writeconfinement is unchanged: writes are still gated by the write-restricted SID list and the
capability-SID allow ACEs; the default DACL only affects objects the confined child creates.
Verification after the fix
workspace-write0xC0000142read-onlyC:\…)lib/runner.jsfrom the archiveVerified on a live installation. The patch was written into the production
resources/app.asar(archive rebuilt; all 11,470 packed entries re-read and byte-compared — 0mismatches; only the target file changed, +92 bytes) and DSH was restarted. With the session back
on the default
workspace-writepolicy:End-to-end,
archify doctor(a Node CLI that previously required switching the session todanger-full-access) now runs confined with all 20 checks passing and exit code 0.The patched
app.asarwas rebuilt byte-exactly: all 11,470 packed entries re-read and comparedagainst the original — 0 mismatches; only the target file changed (+92 bytes), and
node --checkpasses on the patched module.Open question
Identical unpatched code passes when the runner is a plain
node.exeand fails when the runneris
process.execPath(the Electron binary) — same parent, same token origin. The suspicion is thatElectron/Chromium tightens the main process token's default DACL at startup, which is why seeding
only the capability SID is insufficient in production. Not confirmed; the fix above holds either way.
Excluded causes (with evidence)
diagnose-windows-sandbox-acl→NOT_THIS_CLASS, no repairs neededread-onlylist still failsTMP·TEMPrewriteworkspace-write's restricting list is a superset ofread-only's中文摘要
Windows 上
workspace-write(默认)模式下,受限 shell 一律以0xC0000142死亡,read-only正常。根因是
AclSandbox.init()里给受限令牌设置默认 DACL 的那一行:workspace-write下只写入了能力 SID
S-1-4-…,丢掉了read-only会回退到的Everyone。补回Everyone(保留能力 SID)即可修复,且不削弱写入隔离——实测工作区内可写、工作区外仍被拒绝。
All reactions