description: "The sandbox-consuming Bash executor for deployments and maintainers choosing, configuring, or debugging confined command execution with denial and escalation facts."
English | 中文
dsh-bash-sandbox is the sandbox-consuming Bash executor: every command runs as a fresh bash -c process confined through the ctx.sandbox capability instead of with the harness process's full file authority. Each settled result carries the mode the command ran under, whether the sandbox denied a file operation, and how completely the selected runner enforced the requested mode. When no runner can enforce a confined mode, the call fails closed with a structured SANDBOX_UNAVAILABLE error rather than running unconfined. It is the confining sibling of dsh-bash-local — sharing its process mechanics — and the tool layer's escalation fields appear only while it is mounted.
Mount this executor instead of dsh-bash-local when commands must not run with the harness process's full file authority. It registers as ctx.shell and requires a ctx.sandbox provider plus ctx.sandboxPolicy; the model-facing bash tool works over it unchanged and advertises the sandbox_permissions/justification escalation fields.
Choose it when a deployment needs file-level confinement for Bash commands: the configured policy decides the default mode and workspace root, and each session can run under a different mode per call through the tool's escalation flow. The modes govern file effects only — network stays unrestricted and process visibility is backend-specific. For unconfined execution, or when no sandbox backend is available on the platform, mount dsh-bash-local instead.
| Mode | File effects |
|---|---|
read-only (default) |
No writes anywhere; of /dev, only the /dev/null node is writable, so >/dev/null keeps working |
workspace-write |
Writes only under the policy's workspace root plus /tmp (ephemeral under bwrap, the host /tmp under Landlock, /private/tmp plus the per-user temp dir under Seatbelt) |
danger-full-access |
No confinement; the provider is never consulted, and results carry sandbox: { mode, denied: false } |
The executor takes no sandbox configuration of its own: the default mode and workspace root come from ctx.sandboxPolicy, and the runner choice belongs to the ctx.sandbox provider. Its own config is the local executor's knobs verbatim; the generated configuration catalog is the exhaustive source.
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'
- id: sandbox-policy
name: '@deepseek-ai/dsh-sandbox-policy'
config:
mode: read-only
workspaceRoot: !!js process.cwd() # fallback for calls without a session cwd
- id: bash
name: '@deepseek-ai/dsh-bash-sandbox'
A denied command is reported, not retried silently: the result carries sandbox: { mode, denied: true } and the model-facing tool appends the denial marker. When escalation is available, the model may retry the exact command once with the narrowest wider mode and a one-sentence justification; the approval prompt asks the user, and nothing executes before approval. This executor never negotiates permissions itself — the tool layer drives the override.
If no runner can enforce a confined mode, the foreground call fails with SANDBOX_UNAVAILABLE and a background process records a runner-failure fact — never a silent unconfined run. A runner-attributable spawn failure carries the original spawn error as detail; other spawn rejections keep the local executor's ordinary command-start semantics.
Read these pages when the executor contract is not enough. They move from the seam to the sandbox capability this executor consumes.
bash tool and its escalation surface.The generated dsh-tool-bash schemas are the baseline. By advertising a confining sandboxMode, this backend augments bash with sandbox_permissions (enum workspace-write | danger-full-access) and justification. The policy owner separately contributes the current capability-neutral sandbox:policy context.
Small fixed schema increment on requests where bash is visible, plus the current-policy clause owned by dsh-sandbox-policy.
A standing-policy change appends a complete owner-rendered context snapshot after retained history, preserving the existing system/history prefix byte-for-byte. Changing executor capabilities alters the bash schema.
After ordinary bounded output, a denied call appends exactly [sandbox: file access denied under <mode> mode]. When escalation is available it next appends [sandbox: escalation available — retry this exact command once with sandbox_permissions (the narrowest wider mode that suffices) + justification; the approval prompt asks the user]. A settled background runner failure instead appends [sandbox: the sandbox runner itself failed under <mode> mode — the command did not run; this is a sandbox problem, not a command failure].
Zero additional tokens on an unremarkable allowed run beyond ordinary output. Denial or failure adds the quoted conditional marker, retained until compaction.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
If no runner can enforce a confined mode, the foreground call propagates the SANDBOX_UNAVAILABLE error from the sandbox seam. A runner-attributable spawn failure supplies the original spawn error as detail; a rejection without ENOENT/EACCES path or syscall evidence that names argv[0] remains an ordinary command-start error. A settled runner failure supplies the matched fatal stderr line and preserves the original stderr collection; the appended Runner failure: <detail> is the authoritative diagnosis over the generic SANDBOX_UNAVAILABLE prefix.
Conditional error text is visible for that call and retained in history until compaction.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
These limits define when this executor is not a general security boundary. They are current package constraints, not a roadmap.
job_output; a synchronous subprocess throw that names the runner path instead fails start() immediately.danger-full-access deliberately bypasses ctx.sandbox — it is an explicit unconfined mode, not a wider sandbox profile.