Local process-sandbox backends for the DeepSeek Harness sandbox seam: bwrap, the npm-distributed landlock-run launcher, macOS Seatbelt, or the Windows ACL restricted-token runner — functionally probed, fail-closed
$ dsh plugin --profile web add npm:@deepseek-ai/dsh-sandbox-localRun the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial
English | 中文
Local implementation of the dsh-sandbox seam. It selects and caches one platform runner: Linux prefers a working bwrap then Landlock; macOS uses Seatbelt; Windows uses the ACL restricted-token runner. Multiple candidates are probed in order, while a sole candidate is selected directly.
The package root exports the default and named LocalSandboxProvider plugin and Config; platform profile builders stay internal.
Unsupported platforms and unusable runners fail closed with SANDBOX_UNAVAILABLE; execution never silently falls through unconfined. Each wrap carries structured runner-failure rules so consumers can distinguish a broken sandbox from a command failure. The sandbox Agent Note owns selection rationale and profile differences.
Policy is per call; the provider stores only the mechanism and cached runner verdict. Each wrap reports enforcement completeness plus backend-specific denial signatures and runner-failure rules. Landlock requires exit 125 and a landlock-run: fatal line after excluding only the exact partial-enforcement notice; a notice with child exit 1, 2, or 125 remains a child outcome. Bubblewrap and Seatbelt remain signature-only because neither public contract reserves a launcher-failure status. Consumers spawn the returned argv directly, so a missing or unexecutable runner is an out-of-band spawn failure while a successfully launched child exit 126 or 127 remains ordinary. runnerCommand skips probes and requires one or more non-empty, single-line, case-insensitive runnerFailureSignatures entries for the custom runner's own fatal dialect. Because its mechanism is unknown, it carries both Linux denial dialects. probeTimeoutMs bounds functional probes. The sandbox Agent Note owns selection and failure semantics.
The Seatbelt profile is allow-default with (deny file-write*) plus write allow-lists, so exactly the mode's promised file effects are governed: read-only grants the /dev/null literal alone; workspace-write adds the workspace root, /tmp, and the per-user darwin temp dir (os.tmpdir() — the platform's real temp area for mkstemp-family tools), every root canonicalized because Seatbelt matches resolved paths (/tmp IS /private/tmp). Apple marks the sandbox-exec CLI deprecated but ships it on every macOS; the functional probe is what fails closed if that ever changes.
The Windows rung keeps one deterministic write SID and standing ACE per workspace, but gives every live session/workspace pair a random private temp directory with a distinct SID and revocable ACE. Sessions sharing a workspace therefore share its intended write authority without inheriting one another's temp authority. A fresh provider always chooses a new temp path and SID, so crash residue cannot block or authorize a resumed session; agentless calls receive the same per-invocation isolation from the runner. A workspace equal to or containing the platform temp root fails before any ACL mutation because its inheritable workspace ACE would otherwise reach every private temp child.
@deepseek-ai/node-addon-landlock-run supplies the platform launcher, functional probe, and CLI argument vocabulary. This provider owns only mode-to-grant mapping and runner selection. Keeping path resolution and probe parsing with the versioned binary prevents contract drift.
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'
Consumers: @deepseek-ai/dsh-bash-sandbox; see the acp-agent example for the runnable default composition.
Indirectly, through dsh-bash-sandbox and dsh-tool-bash, which render this provider's enforcement and denial facts while the dsh-sandbox seam owns the SANDBOX_UNAVAILABLE text and runner selection and profiles stay outside context.
No direct invalidation; the named consumer owns any request-prefix changes.
enforcement: 'partial' rather than overstating that boundary as full.enforcement: 'partial' rather than overstated as full.sandbox-exec — macOS still ships it, but this provider cannot replace or probe that private policy engine if Apple removes it.runnerCommand is an operator assertion — a configured custom runner skips functional probes and is assumed to implement the bwrap-compatible profile honestly; if it is itself a Bash script, its interpreter startup runs before that script applies confinement.