dsh-acl-sandbox-patch
Temporary fix for the DSH 0.1.7 Windows ACL sandbox failing on non-system-drive workspaces (grantWrite / SetNamedSecurityInfoW Win32 5) — restores workspace-write commands without touching any system ACL.
What it is
Temporary fix for the DSH 0.1.7 Windows ACL sandbox failing on non-system-drive workspaces (grantWrite / SetNamedSecurityInfoW Win32 5) — restores workspace-write commands without touching any system ACL.
How to install
Run this in the DSH web profile, then refresh the page.
$ dsh plugin --profile web add 'git+https://github.com/masknull/dsh-acl-sandbox-patch.git#a63015b8bacdfd39066da6fcead468bc753f04ef'
DSH versions accepted
>=0.1.7-rc.1
Author and traction
masknull · ★ 13 · Updated 2026-09-25
About this plugin
dsh-acl-sandbox-patch
English: [README.en.md](README.en.md)
DSH 0.1.7 Windows ACL 沙箱在非系统盘工作区(D:/E:/F:,目录 DACL 只有 Authenticated Users: Modify、没有本机用户 FullControl)下的临时修复插件:不动任何系统 ACL,让 workspace-write 的命令恢复可执行。
修的是什么
0.1.7 起 workspace-write 的每条命令在 spawn 前都要给工作区做 ACL 授权,@deepseek-ai/dsh-sandbox-windows-acl 用一次 SetNamedSecurityInfoW 同时下发三样东西:capability SID 的 Allow ACE、world SID 的 FILE_DELETE_CHILD Deny ACE、Low 完整性强制标签。写标签要求调用者对该目录持有 WRITE_OWNER,而:
- 非系统盘新建目录的默认 ACL 不含创建者 FullControl(只有继承来的 Modify);
- DSH 跑在 UAC 过滤令牌下,
BUILTIN\Administrators是 deny-only,吃不到组的 FullControl; - 属主隐式权限只有
READ_CONTROL + WRITE_DAC,不含 WRITE_OWNER。
于是授权返回 ERROR_ACCESS_DENIED (5),沙箱 fail-closed,命令从未 spawn:
SetNamedSecurityInfoW failed (Win32 5): grantWrite()
不受影响的场景:read-only 策略(不授予可写根,走不到这个调用);位于 %USERPROFILE% 下的工作区(用户 Profile 天生给用户 SID FullControl)。
上游已知问题(rc.2 的沙箱包与 rc.1 逐字节相同,未修复):
- [Discussion #7771 — 工作区所有者问题触发](https://github.com/deepseek-ai/deepseek-harness/discussions/7771)
- [Discussion #7720 — 同一缺陷的另一半触发条件](https://github.com/deepseek-ai/deepseek-harness/discussions/7720)
- [Discussion #7804 — 更细的实验报告](https://github.com/deepseek-ai/deepseek-harness/discussions/7804)
运行要求(最低支持版本)
| 项 | 要求 |
|---|---|
| 操作系统 | Windows(NTFS;其他平台插件自动 no-op) |
| DSH 最低版本 | >= 0.1.7-rc.1(该版本引入 @deepseek-ai/dsh-sandbox-windows-acl,bug 于此引入;0.1.5 及更早无此沙箱,无需本插件) |
| 已验证版本 | 0.1.7-rc.1 / 0.1.7-rc.2(两者沙箱包逐字节相同) |
| 策略 | 仅 workspace-write 需要(read-only / danger-full-access 不需要) |
engines.dsh 已声明 >=0.1.7-rc.1。若未来 DSH 修复了该问题(对应 discussion 关闭或沙箱包升级),本插件的严格路径会直接成功、行为退化为无异于出厂,届时卸载即可。
原理
只包装沙箱自己发起的 FFI 调用,两条注入路径互兜底:
| 路径 | 覆盖对象 | 机制 |
|---|---|---|
| A. koffi 钩子 | 所有 node 子进程(sandbox runner、探针) | hook Module._load 拦 require('koffi'),包装 koffi.load() 返回对象的 .func(),对 dsh-win32-process 的 4 参数调用形式返回包装函数(C 声明式形式原样透传)。随 NODE_OPTIONS=--require=lib/preload.cjs 预加载,早于主模块图 |
| B. api 表直改 | DSH 服务端进程(负责 workspace standing grant) | 解析沙箱包后创建一次性 AclWriteGrant 物化进程级共享绑定表,直接替换表上目标属性后 dispose。与绑定时序无关 |
包装逻辑(lib/preload.cjs):
1. SetNamedSecurityInfoW:先按原语义完整尝试(含 Low 标签);仅当返回 Win32 5 时降级重试为 DACL-only(剥掉 LABEL_SECURITY_INFORMATION,SACL 传 NULL)。DACL 写入只需要属主隐式的 WRITE_DAC,可以成功。
2. SetTokenInformation(TokenIntegrityLevel=25):双判据命中其一即跳过把子进程令牌降到 Low——工作区没有 Low 标签,Low 子进程按 no-write-up 什么都写不了。判据 1:状态文件(插件目录 .degraded.state 主路径)/ 环境变量 / 进程标志;判据 2:runner 从自身 argv 取 --workspace 直侦该目录有无 Low 标签(无 ⇒ 降级环境)。判据 2 不依赖任何文件与环境,是最终兜底。
3. GetNamedSecurityInfoW:降级发生后,对含 LABEL 位的查询返回合成的"已带精确 Low 标签" SACL(与 hasExactLabel 的逐字段比对同构),让幂等跳过重新命中。
环境健康时行为与出厂一致(完整授权、正常降完整性);只有真的打不上标签的环境才降级。
安全边界(诚实话在此)
保留:
WRITE_RESTRICTED受限令牌(正常 SID + 限制 SID 双列表访问检查)- capability SID Allow ACE——只有工作区和会话私有 temp 可写
- world SID
FILE_DELETE_CHILDDeny——删除权限收敛到 capability ACE - fail-closed:其他任何 Win32 失败照旧抛错,绝不去掉沙箱
失去(仅发生在本来就打不上 Low 标签的环境):
- Low 完整性强制标签这一层纵深防御(子进程不再被强制 Low 完整性)
本来就没有的(与出厂一致,未变化):读限制、网络限制、进程可见性限制。
安装
dsh plugin --profile web add github:masknull/dsh-acl-sandbox-patch
该命令会链接包、记入依赖,并因包声明了 dsh.bundle 而自动加入 profile 的 bundle 列表。重启 DSH 使新的 bundle 层生效,启动日志应出现:
[dsh-acl-sandbox-patch] active — Windows ACL 沙箱 Low 标签/完整性降级补丁已安装(上游 Discussions #7771/#7720/#7804)
新会话里直接执行 shell 命令——不再逐条提权批准,也不再报 Win32 5。
> 供应链安全可固定提交:github:masknull/dsh-acl-sandbox-patch#。
验证
装好后最直接的验证:新会话跑 whoami / echo hi,无需批准、有输出;再试覆写一个文件、在沙箱里 New-Item 建个文件——都应直接成功。
实测记录(非系统盘上共 44,251 个文件的工作区,DSH 0.1.7-rc.2,v0.1.2):
| 场景 | 结果 |
|---|---|
| 未打补丁 | 任何命令 spawn 前失败:SetNamedSecurityInfoW failed (Win32 5): grantWrite() |
| 打补丁后普通 pwsh 执行 | 直接返回,无需逐条批准 |
| 重启 DSH 后首条 workspace-write 命令 | 约 20 秒(一次性 DACL 全树传播,固有代价) |
| 之后同进程内的命令 | 约 1.7 秒 |
| 新开会话的命令 | 2 秒以内(seam 的 per-provider 复用缓存生效) |
| 沙箱内令牌完整性(v0.1.2 关键指标) | Medium(0.1.1 及以前为 Low,沙箱内写文件全被 no-write-up 拒) |
| 沙箱内文件操作(新建/覆写/删除) | 全部正常(0.1.1 及以前全部 Access denied) |
Compare in this category
The five most-starred plugins in the same category.
| Plugin | Author | Stars | Version | Updated |
|---|---|---|---|---|
| Mole | tw93 | 74.5K | 0.0.0 | 2026-11-10 |
| DeepSeek-Reasonix | esengine | 36.1K | 0.0.0 | 2026-11-10 |
| dsh-desktop | anywhere-labs | 35.6K | 0.4.1 | 2026-11-06 |
| awesome-dsh-plugin | awesome-dsh-plugin | 24.1K | 0.1.0 | 2026-11-10 |
| dsh-market | dsh-market | 11.8K | 1.73.17 | 2026-11-09 |