description: "The sandbox-consuming Bash executor for deployments and maintainers choosing, configuring, or debugging confined command execution with denial and escalation facts."
English | 中文
Use dsh-bash-sandbox to run each Bash command with file-access confinement instead of the harness process's full authority. Results report the selected mode, denied file operations, and whether the runner fully enforced that mode. If no runner can enforce a confined mode, the command fails with SANDBOX_UNAVAILABLE rather than running unconfined. Choose it when deployments need file isolation; network access and process visibility remain outside its guarantees.
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 provider rejection is attributed to the confinement runner only when its ENOENT/EACCES path or syscall independently names argv[0]; otherwise it keeps the local executor's stage-neutral provider-failure 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 provider rejection with ENOENT/EACCES path or syscall evidence that names argv[0] supplies the original error as runner-failure detail; another rejection remains a stage-neutral provider 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.