[Bug] Windows:工作区位于非系统盘时 ACL 沙箱必然初始化失败(Win32 5 / grantWrite)/ ACL sandbox fails on non-system drives: the default ACL grants the caller no WRITE_OWNER #7804
Replies: 2 comments
A correction to suggested fix 5, and where your
|
〇、先道谢,也先道歉谢谢你逐条核实,并把我们的观测采纳进了 0.5.0 的分叉逻辑 —— 这直接让非系统盘的用户拿到了可粘贴的修复命令;也谢谢你引用这份报告、把它和 #7750 / #7816 串成了一条完整的证据链。同时要为我们那份报告道歉:两条建议里,一条的前提是错的,另一条的一半会造成静默损坏,正文里还有一处「等价替代」写错了。以下是逐条更正。 Thank you — and apologies. Thank you for checking this line by line and for folding our observation into 0.5.0's branching, which puts a paste-ready fix directly in front of non-system-drive users; and for citing this report and tying it together with #7750 / #7816 into one evidence chain. Apologies for our report: of its two suggestions, one rests on a false premise and half of the other would produce a silent break, and one "equivalent" line in it is simply wrong. Corrections follow. 一、先接受两处更正 —— 我们撤回建议 5,并收窄建议 2我们独立复读了 0.1.7-rc.2 的编译产物,你说的两处都成立。 建议 5(
⇒ 建议 2 的「跳过标签降级」—— 撤回;只保留诊断那一半。 我们核实 二、我们报告里的一处错误,由我们自己更正正文 A 节把 三、一处场景归属需要澄清(对你的 advisory 有直接影响)本报告的场景是非系统盘 + 目录所有者就是调用者本人,不是 #7771 的 我们刚在受影响的机器上做了最小复现(Windows 11 / NTFS / 非系统盘 ⇒ 在「非系统盘 + 自己拥有」这一格里,最小充分权限就是 四、一条补充观察:沙箱内的 agent 无法自救我们在 English version1. Two corrections accepted — we withdraw suggestion 5 and narrow suggestion 2 We re-read the compiled 0.1.7-rc.2 artifacts; both of your points hold. Suggestion 5 (
⇒ The "skip the label" half of suggestion 2 — withdrawn; only the diagnostic half stays. 2. A correction to our own report Section A listed 3. One attribution that directly affects your advisory This report's environment is non-system drive + the caller is the directory owner — not #7771's We just ran the minimal reproduction on an affected machine (Windows 11 / NTFS / non-system drive ⇒ For "non-system drive + caller-owned", the minimal sufficient right is 4. One extra observation: an agent inside the sandbox cannot repair this itself Running the same |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
环境 / Environment
Windows 11,全部卷均为 NTFS(
Get-Volume确认,不是 FAT 卷)DSH
0.1.7-rc.2(npmnext通道);沙箱后端@deepseek-ai/dsh-sandbox-windows-acl(随 0.1.7-rc.2 提供)文件策略:
workspace-write工作区:非系统盘上的目录(
F:\<workspace>,不在%USERPROFILE%之下)进程身份:普通用户(未提权),
whoami /groups显示Mandatory Label\Medium Mandatory LevelWindows 11, all volumes NTFS (
Get-Volumeconfirms; it is not a FAT volume)DSH
0.1.7-rc.2(npmnextchannel); sandbox backend@deepseek-ai/dsh-sandbox-windows-acl(shipped with 0.1.7-rc.2)File policy:
workspace-writeWorkspace: a directory on a non-system drive (
F:\<workspace>, not under%USERPROFILE%)Process identity: regular user (unelevated);
whoami /groupsshowsMandatory Label\Medium Mandatory Level现象 / Symptom
将文件策略设为
workspace-write后,所有 pwsh / bash 调用立即失败 —— 连无副作用的最小命令都不行:With the file policy set to
workspace-write, every pwsh / bash invocation fails immediately — even a side-effect-free minimal command:同一会话内把策略切回
danger-full-access,同一条命令立刻正常。⇒ 失败发生在沙箱初始化阶段(子进程尚未创建),不是命令本身的问题。Switching the policy back to
danger-full-accessin the same session makes the very same command work immediately. ⇒ The failure happens during sandbox initialization (no child process is ever created), so it is not about the command itself.按包内 README 的说明,
init()是 fail-closed:任何 Win32 失败都会抛错、绝不 spawn 未受限的子进程 —— 这个行为本身是对的;问题在于该环境下永远无法满足grantWrite的前提,而且用户拿不到可操作的提示。As the package README states,
init()is fail-closed: any Win32 failure throws and an unrestricted child is never spawned — that behavior is correct; the problem is that in this environment the precondition ofgrantWritecan never be satisfied, and the user gets no actionable hint.根因 / Root cause
grantWrite()在一次SetNamedSecurityInfoW调用里同时改 DACL 与 SACL 的 mandatory integrity label(LABEL_SECURITY_INFORMATION)。grantWrite()changes the DACL and the SACL's mandatory integrity label (LABEL_SECURITY_INFORMATION) in a singleSetNamedSecurityInfoWcall.READ_CONTROL+WRITE_DAC;写标签需要WRITE_OWNER(与包内 README「被授权目录必须由调用者拥有并授予WRITE_OWNER」的已知限制一致)。A directory's owner implies only
READ_CONTROL+WRITE_DAC; writing the label needsWRITE_OWNER(consistent with the package README's known limitation: the granted directory must be owned by the caller withWRITE_OWNERgranted).NT AUTHORITY\Authenticated Users: Modify+BUILTIN\Users: ReadAndExecute(继承),不含创建者/调用者的 FullControl ⇒ 调用者没有WRITE_OWNER。A non-system drive's default ACL is
NT AUTHORITY\Authenticated Users: Modify+BUILTIN\Users: ReadAndExecute(inherited) and does not include FullControl for the creator/caller ⇒ the caller lacksWRITE_OWNER.SetNamedSecurityInfoW返回ERROR_ACCESS_DENIED (5),init()fail-closed 抛错。Hence
SetNamedSecurityInfoWreturnsERROR_ACCESS_DENIED (5)andinit()throws, fail-closed.对照事实:
C:\Users\<user>\…下新建的目录天生带调用者FullControl(继承),因此同样代码在系统盘用户目录下工作正常 —— 这也是为什么该问题在常规开发环境下不会被发现。For contrast: directories created under
C:\Users\<user>\…inherit FullControl for the caller, so the same code works fine there — which is exactly why this problem is invisible in the usual development setup.最小复现 / Minimal reproduction
不需要启动 DSH,用系统自带
icacls就能复现同一条权限路径:No DSH install needed — the built-in
icaclsreproduces the very same privilege path:对照实验:在
C:\Users\<user>\下重复第 1~2 步 —— 天生成功(新目录继承调用者 FullControl)。Control experiment: repeat steps 1–2 under
C:\Users\<user>\— it succeeds out of the box (new directories inherit FullControl for the caller).影响 / Impact
workspace-write完全不可用(AI 无法执行任何 shell 命令),只能退到danger-full-access—— 恰好是沙箱想要避免的那个状态。这属于静默降级成不安全配置的路径。Any Windows user whose workspace lives on a non-system drive:
workspace-writeis entirely unusable (the agent cannot run any shell command), forcing a fallback todanger-full-access— precisely the state the sandbox exists to prevent. This is a silent downgrade to an unsafe configuration.Win32 5,没有说明"该目录缺少WRITE_OWNER",也没有修复办法;README 里的限制说明在故障当下不可见(用户看到的只是 GUI 里一条报错)。The error is a bare
Win32 5with no mention that the directory lacksWRITE_OWNERand no fix; the README limitation is invisible at failure time (all the user sees is one error line in the GUI).The failure is deterministic and stable (not a race), which effectively drives this class of users away from the sandbox.
修复方法 / How to fix
A. 立刻可用(用户侧)/ Immediately available (user side)
给工作区目录补一条调用者的完全控制(含
WRITE_OWNER),沙箱即可正常初始化:Grant the workspace directory FullControl for the caller (which includes
WRITE_OWNER) and the sandbox initializes normally:(等价替代:
icacls <workspace> /setowner "<user>",或把工作区放到C:\Users\<user>\…之下。)(Equivalents:
icacls <workspace> /setowner "<user>", or simply put the workspace underC:\Users\<user>\….)B. 根治(上游)/ Proper fix (upstream)
init()之前对每个 writable root 做能力探测(能否写 SACL / 是否具备WRITE_OWNER)。失败时给出可直接粘贴的修复命令(即上面那条icacls)与文档链接,而不是只抛 Win32 码。Pre-flight check + actionable guidance: probe each writable root's capability (can it write the SACL / does it have
WRITE_OWNER) beforeinit(), and on failure print the paste-ready fix command above plus a doc link, instead of a bare Win32 code.Optional degradation instead of total failure: when the SACL label write fails, could DSH still apply the capability ACE and continue, while clearly reporting reduced isolation strength? (Or at least distinguish "DACL write failed" from "label write failed" in the error.) Today's cost — the entire command path dying — is larger than the missing Low label.
Document the precondition (both README and UI): the workspace must live in a directory the caller fully controls; non-system drives do not satisfy this by default — include the one-time grant step.
--grant-workspace-acl):在用户知情下完成能力 SID 授权与 Low 标签施加,与当前 standing-grant 的设计一致(保持"常驻 ACE 作复用缓存"的既有语义)。Optional explicit initialization command (e.g.
--grant-workspace-acl): perform the capability-SID grant and Low label on the user's explicit behalf, consistent with today's standing-grant design ("persistent ACE as a reuse cache").read-only建议纳入同一预检:它本身不 grant,但 spawn 的 Low 完整性令牌仍依赖标签可达性。read-onlyshould share the same pre-flight: it grants nothing itself, but the spawned Low-integrity token still depends on the label being reachable.相关 / Related
BUILTIN\Administrators)/ the other entry point of the same defect (directory owner isBUILTIN\Administrators)本报告由 DSH agent 定位整理、经人工复核。
Located and written up by a DSH agent, reviewed by a human before posting.
All reactions