Repository navigation
Replies: 5 comments
|
The isolation results make a strong case for the token's default DACL being the issue, rather than the workspace ACLs themselves. I'd agree with separating the two responsibilities: the default DACL needs to let the child access objects it creates, while the restricted-token SIDs and workspace ACLs determine which filesystem locations it can write to. One thing I'd add to the proposed fix is a regression test that checks both functionality and confinement:
That last pair matters because fixing the startup failure alone wouldn't demonstrate that the sandbox still enforces its intended restrictions. I'd also make the availability probe exercise the selected mode, as suggested, so this fails before a real command is dispatched rather than forcing users into repeated permission escalations. |
|
Thanks for the review — I agree on both points.
On the separation: yes. The token's default DACL only needs to let the child reach the objects it creates itself; the restricting SIDs and the workspace ACLs are what actually bound where it can write. That's the shape the fix takes — the default-DACL grant goes back to Everyone (matching the already-working read-only path), and the write allowlist is left entirely to the restricting SIDs plus the capability ACE on the workspace DACL.
On the regression test: added, and it covers functionality and confinement together:
workspace-write: launch a trivial child → exits 0
workspace-write: write and read back a file inside the allowed workspace
workspace-write: attempt to write outside the allowed workspace → denied
read-only: launch a trivial child → exits 0
Checks 3 and 4 are the ones that keep the fix honest — a passing launch on its own would not show that the write allowlist is still enforced. All four pass on the patched build.
I also folded in the probe change you suggested: defaultProbeWindowsAcl now exercises workspace-write (the mode that is actually dispatched) instead of read-only, so a regression surfaces as SANDBOX_UNAVAILABLE before any real command is sent, rather than as a per-call escalation loop.
Full write-up, the isolation evidence, and the runnable test are in discussion #9507.
|
|
Nice, that covers both the launch failure and the sandbox restrictions. Glad the probe change worked out too. Thanks for checking all four cases! |
|
This is a useful isolation of the problem, especially the comparison between One detail I think is worth evaluating before settling on The important requirement seems to be that the selected SID must satisfy both access checks:
A capability SID that only exists in the restricting list cannot satisfy both checks on its own.
I'd suggest including regression coverage for:
The last case is particularly important. A successful This doesn't replace the proposed fix, but it could help verify that the DACL change restores process startup without accidentally broadening workspace write permissions. I haven't reproduced the failure locally, so I'm treating this as an additional verification suggestion rather than a confirmed alternative patch. |
|
Tested it — you were right. I swapped the default-DACL trustee from Everyone;to the session's logonSid;and reran the regression suite: all four checks still pass (workspace-write launch, write+read inside the workspace, write outside denied, read-only launch), and the write allowlist is unchanged. logonSid;is the narrower choice — it's in both the token's normal groups and the restricting list, so it satisfies both access checks without widening the default DACL to the whole machine. Report updated to use it, with credit. Thanks!
|
Uh oh!
There was an error while loading. Please reload this page.
Windows ACL sandbox:
workspace-writechild dies with 0xC0000142 (STATUS_DLL_INIT_FAILED)TL;DR
@deepseek-ai/dsh-sandbox-windows-aclgives the restricted token a default DACL thatgrants full access to the write capability SID (
S-1-4-x-y), a SID that exists only inthe token's restricting list and is absent from the token's normal groups. Any object the
child creates with that default DACL therefore fails the child's own pass-1 access check, so
early DLL initialization dies with
STATUS_DLL_INIT_FAILED(0xC0000142).read-onlyisunaffected because it grants
Everyone(which is in the normal groups). One-line fix:always use
Everyonefor the token default DACL.Environment
OS: Windows 11 Pro, build 10.0.26200
Harness:
@deepseek-ai/dsh0.2.0-rc.2 (bundled in DSH Desktop 0.11.1)Profile:
web(DSH_PROFILE=web), hosted by the Electron desktop appSandbox mode:
workspace-write(the deployment default)Symptom
Every confined shell command fails: the pwsh/bash executor wraps the command with the
windows-acl runner, the restricted child exits
3221225794(=0xC0000142,STATUS_DLL_INIT_FAILED) with no output, and the tool must escalate todanger-full-accessfor every call.Reproduction
Run the shipped runner directly (on the Desktop app use
ELECTRON_RUN_AS_NODE=1with theElectron binary as
node, since the asar is not plain-node readable):Root cause (verified by isolation)
Using the public
AclSandboxAPI (allworkspace-write,manageDaclsoff to avoid ACL edits):token default DACL restricting list exit code
Everyonelogon + Everyone (+cap SID) 0Everyonelogon + Everyone 0cap SID logon + Everyone + Everyone 0xC0000142
cap SID logon + Everyone + cap SID 0xC0000142
The failure tracks the token default DACL exactly, not the restricting list, not the
directory ACL grants, and not the private temp directory.
S-1-4in the restricting listis fine; the crash happens only when
S-1-4(or any SID absent from the token's normalgroups) is merged into the token default DACL.
AclSandbox.init()calls:setTokenDefaultDaclGrantmerges a full-access ACE for that SID into the token's inheriteddefault DACL. The chosen SID is the write capability SID, which is present only in the
WRITE_RESTRICTEDrestricting list — not in the token's normal groups. Objects the childcreates with this default DACL are therefore unreachable by the child's own pass-1 check,
breaking the loader's early object setup.
read-onlypicksworldSid(Everyone), which isin the normal groups, so it works.
Proposed fix
packages/sandbox/sandbox-windows-acl/src/index.tsAlways grant
Everyonein the token default DACL (identical to the already-workingread-onlypath). The workspace write allowlist is enforced by theWRITE_RESTRICTEDrestricting SIDs plus the capability ACE on the workspace DACL; the token default DACL only
governs objects the child newly creates.
packages/sandbox/sandbox-local/src/index.tsdefaultProbeWindowsAclprobes--mode read-onlyonly, and on Windows the ACL runner is thesole candidate and is therefore never probed at all — a broken
workspace-writebackend issilently selected instead of surfacing as
SANDBOX_UNAVAILABLE. Probe the mode that isactually used (
workspace-write) on a disposable temp directory so a regression like thisfails loud and fails closed.
Impact
Every user on Windows Desktop running the default
workspace-writepreset cannot run anyconfined shell command (per-call escalation workaround only).
The workspace directory has already been modified persistently by the sandbox
(
Everyone (CI)(DENY)(DC), a capability-SID grant, and aLowmandatory label), which isby-design standing state and is not revoked by
dispose().All reactions