dsh-grantwrite-patch
English | 中文
Windows sandbox ACL-repair plugin for DeepSeek Harness (dsh) — fix the grantWrite failure (SetNamedSecurityInfoW Win32 5) and retry the command invisibly.
What it solves
On Windows, the workspace-write sandbox writes a write grant into the workspace root DACL before every command (AclWriteGrant.add → grantWrite). When any directory on the chain lacks an effective WRITE_DAC/WRITE_OWNER, SetNamedSecurityInfoW fails with Win32 5 (ERROR_ACCESS_DENIED), and every confined command on that workspace fails before spawn:
Error: SetNamedSecurityInfoW failed (Win32 5): grantWrite
This plugin intercepts that error, repairs permissions automatically, and retries the command so you keep working without noticing.
How it works
The plugin picks a strategy from the workspace size:
- Normal workspaces: intercept the error in memory and retry with zero side effects — no file permissions are touched.
- Large workspaces: when the object count exceeds the threshold (20,000 by default), proactively apply a full grant to the workspace once, so the write grant is not re-paid on every DSH restart and large trees stop costing you waiting time.
- Fallback: when the above cannot apply, run the diagnose script once to repair permissions and retry; when the script is unavailable, fall back to an
icaclsgrant.
The three paths never conflict; they stack on demand.
Requirements
| Item | Requirement |
|---|---|
| OS | Windows (NTFS). The plugin disables itself on other platforms |
| DSH version | >= 0.1.7-rc.1. The full diagnose-script repair needs >= 0.2.0-rc.2 |
| Sandbox policy | Only workspace-write needs this (read-only / danger-full-access do not) |
Install
From npm
dsh plugin --profile web add dsh-grantwrite-patch
From source (GitHub)
git clone https://github.com/0-v-0/dsh-grantwrite-patch
cd dsh-grantwrite-patch
pnpm install && pnpm build
dsh plugin --profile web add .
Notes:
dsh pluginbehaves like adding a dependency to your profile. A bundle plugin is loaded once its full package name appears in the profile'sdsh.profile.bundleslist (added automatically); the bundle patch (cordis.patch.yml) applies on the next boot.- The source install must run
pnpm buildfirst:lib/is not committed, and the FFI preload is resolved from the installed package (lib/preload.cjs). - To update, run the same command again (
add dsh-grantwrite-patch@latest). - Alternatively, merge the
- insert:block ofcordis.patch.ymlinto the host'scordis.ymlby hand.
Configuration
- insert:
id: grantwrite-patch
name: dsh-grantwrite-patch
config:
enable: true
mode: auto # auto | patch | repair
objectThreshold: 20000 # object count at/above which a workspace counts as large -> persistent repair
probeTimeoutMs: 10000 # size-probe timeout; a timed-out probe counts as large
probeCooldownMs: 3600000 # per-workspace probe/decision cache duration
repairTimeoutMs: 120000
maxRetries: 1
cooldownMs: 60000
appendDiagnostics: true
grantFallback: true # fall back to a bare icacls grant when the diagnose script is unavailable (0.1.7) or fails; drive roots refused
# scriptPath: <absolute path> # default: resolved from @deepseek-ai/dsh-sandbox-windows-acl package assets (DSH >= 0.2.x)
# outDir: <absolute path> # default: $DSH_HOME/grantwrite-patch (~/.dsh/grantwrite-patch without DSH_HOME)
Security model
- patch path: touches no system ACL and leaves no persistent side effect; the
WRITE_RESTRICTEDrestricted token, capability-SID Allow ACEs, and the world-SIDFILE_DELETE_CHILDDeny are preserved. The only thing lost is the Low-integrity label layer of defence in depth (children run at Medium), and only on hosts that could not apply the label in the first place. - repair path: the repair scope is bounded by the script's
-AllowRoot: only the target directory or objects strictly inside it are modified; reparse points and managed-application trees are refused; deny ACEs are never deleted; every change is backed up first and re-read for verification, and a failed batch is rolled back. - grant fallback (
grantFallback): when the script is unavailable or fails, run a bareicacls <root> /grant "<user>:(OI)(CI)F". Drive roots are hard-refused (isDriveRoot:D:\and other drive roots are refused; only real workspaces are granted); inheritance policy is untouched and deny ACEs are not removed; roll back withicacls <root> /remove:g "<user>". The script is preferred (safer:-AllowRootbound + backup + verify); the fallback only covers the gap. - The plugin process is the host process (a non-restricted token); modifying permissions is exactly what the sandbox's restricted token cannot do. The plugin never elevates its token.
- Only
SetNamedSecurityInfoWfailures in agrantWritecontext are matched; other Win32 failures, command exit codes, EPERM, and so on all pass through untouched. - The retry happens once (
maxRetriesis tunable from 0 to 3); a failed repair is not retried, which prevents loops.
Credits & License
The FFI patch core is adapted from masknull/dsh-acl-sandbox-patch.
No comments yet. Be the first to write one.