[Bug] Windows: windows-acl rung is auto-selected without a probe, but its host-side write grant always fails without SeSecurityPrivilege
#7622
Replies: 2 comments
|
Thanks — this is the second report of this exact signature in two days, and its two halves land very differently. One half is already-diagnosed territory where the evidence shape does not decide the question; the other is new, correct, and wider than you state. Taking them in that order. The
|
|
Follow-up from the reporter: we ran the two discriminators you named. You were right, and our Environment: Windows 11, 1. Read-only —
|
Uh oh!
There was an error while loading. Please reload this page.
[Bug] Windows:
windows-acl沙箱档位免探测即被选中,但其宿主侧 write grant 必然失败 → workspace-write 下每条命令都报 Win32 5版本:
@deepseek-ai/dsh0.1.7-alpha.1 | 平台:Windows 11 + PowerShell 7.6.6 | 宿主权限:非提权标准用户(Medium 完整性)Summary
On Windows, the ACL sandbox rung (
windows-acl) is selected without a probe (it is the only candidate inPLATFORM_CHAINS.win32), yet its host-side write grant unconditionally writes a Low mandatory integrity label into the object's SACL. Writing a SACL requiresSeSecurityPrivilege, which a non-elevated host token does not have. The result:workspace-writemode fails withSetNamedSecurityInfoW failed (Win32 5): grantWrite(<workspace>);manageDacls: falseand never writes a SACL);danger-full-accessto get any work done.Environment
@deepseek-ai/dsh0.1.7-alpha.1win32), PowerShell 7.6.6S-1-16-8192), not elevatedwhoami /privon the host process shows only:→ no
SeSecurityPrivilege.Impact
Observed over 39 recorded sessions (≈850 shell tool calls):
workspace-writemode: 0 successes out of 6 real attempts; every attempt returnedError: SetNamedSecurityInfoW failed (Win32 5): grantWrite(<workspace>).danger-full-access: 828 success / 23 ordinary non-zero exits.danger-full-access,i.e. the file sandbox is effectively off — not because the user chose that, but because the
only alternative silently fails. This weakens the confinement the feature is meant to provide.
A teammate/session started with
approval: neverhas no recovery path at all: it cannotescalate, and every command fails.
Root cause
The rung is chosen without any probe.
dsh-sandbox-local/lib/index.js:Per the accompanying comment, a chain is probed "only when it has MORE than one candidate".
With a single candidate,
windows-aclis accepted unconditionally.The probe, if it did run, would not see the failure.
defaultProbeWindowsAclspawns therunner with
--mode read-only:while
dsh-sandbox-windows-acl/lib/runner.jssetsmanageDacls: !seamManaged— i.e. therunner deliberately does not manage DACLs/SACLs. The part that does is the host-side
AclWriteGrant, and that is never probed.The host-side grant always writes a SACL.
grantWriteindsh-sandbox-windows-acl/lib/types-*.js:and
mergeAndApplyapplies it withSecurityInfo = 20(DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION):When not short-circuited it is always
kind: "apply", i.e. the label edit rides in thesame call as the DACL edit → writing the SACL is unavoidable.
No privilege is ever enabled. A repository-wide search of
dsh-sandbox-windows-aclforAdjustTokenPrivileges/LookupPrivilegeValue/SeSecurityPrivilegereturns zero hits. The package assumes the token can write SACLs.The short circuit cannot be leveraged as a workaround. It requires the capability ACE,
the deny ACE and the label to match simultaneously:
workspaceWriteSid(workspaceRoot)is deterministic, so a one-time pre-grant could match —but
tempWriteSid(mkdtempSync(join(tmpdir(), "dsh-")))is a fresh random directory persession, so the temp grant never matches and always takes the
applypath.Pre-placing an inheritable Low label on
%TEMP%does not help either, because theshort circuit is all-or-nothing.
Evidence / reproduction
Token lacks the privilege —
whoami /priv(above);Get-Acl -Path <dir> -Auditon anydirectory returns:
Independent reproduction without DSH — set the same integrity label on a scratch directory:
Exit code 5 =
ERROR_ACCESS_DENIED, exactly the Win32 code DSH reports.Reproduced through DSH — with the session in
workspace-write, the very first command:{"tool":"pwsh","command":"Get-ChildItem \"D:\\...\\node_modules\\@deepseek-ai\" -Name"}returns:
The DACL-only path is not the blocker: the workspace directory is owned by the calling
user and grants them full control, so
WRITE_DACis available. Only the SACL edit fails.Why we believe this is not machine-specific
The failing operation is guarded by a token privilege, not by any directory ACL, so it should
reproduce on any Windows host whose dsh process is not running with
SeSecurityPrivilege(i.e. any ordinary non-elevated user, which is the normal way to run the web/desktop app).
Proposed fixes (any one would resolve the reported failure)
AclSandboxinit, when the token holdsSeSecurityPrivilege(admin tokens have it, disabled by default), enable it via
LookupPrivilegeValue+AdjustTokenPrivilegesfor the grant duration.partialwith a surfacedwarning, or
(so a session never begins in a mode where every command is guaranteed to fail).
defaultProbeWindowsAclexercise the host-side grant(create a throwaway directory, call
AclWriteGrant.add, revoke, remove) rather than onlystarting the runner. This would make the rung
unusableon affected hosts and let theplatform chain report that properly.
Workaround we applied locally
In the profile patch layer:
i.e. default new sessions to full access while keeping the approval gate, purely so that
sessions stop starting in an unusable mode. This is a mitigation, not a fix: it means the file
sandbox is knowingly off.
Reported after a 39-session / ~65 MB execution-trace review of Windows shell failures.
Full local evidence:
docs/kb-exec复盘与Windows原生化评估.md§8.All reactions