|
|
пре 1 месец | |
|---|---|---|
| .. | ||
| src | пре 1 месец | |
| tests | пре 1 месец | |
| README.md | пре 1 месец | |
| package.json | пре 1 месец | |
| tsconfig.json | пре 1 месец | |
Sandbox-consuming implementation of the @deepseek-ai/dsh-bash executor seam. Load it instead of @deepseek-ai/dsh-bash-local, together with a ctx.sandbox provider (e.g. @deepseek-ai/dsh-sandbox-local) and a ctx.sandboxPolicy (which owns the default mode + workspace root, shared with the sandboxed filesystem) — no alternate tool plugin is needed; dsh-tool-bash detects the executor's sandboxMode capability and adds the escalation fields.
The package root exports the default and named SandboxBashExecutor plugin plus its Config; quoting and result-classification helpers stay internal.
Every command is confined by handing the provider the exact ['bash', '-c', command] argv this executor is about to spawn and spawning the returned (wrapped) argv instead. WHICH platform runner confines it — and whether one is usable at all (fail closed with a structured SANDBOX_UNAVAILABLE error, never a silent unconfined run) — is the provider's concern; this package owns the bash side only.
| 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 workspaceRoot + /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. Foreground results carry sandbox: { mode, denied: false }; background process handles carry no sandbox facts. |
Semantics:
BashRunResult.sandbox.denied: true (conservative classification, read from the collected stderr tail); every CONFINED run also carries the mode it executed under (result.sandbox.mode) and the provider's enforcement completeness (result.sandbox.enforcement: full, or partial on an older Landlock ABI).SANDBOX_UNAVAILABLE; a settled background process stamps process.sandbox.runnerFailed, which the bash producer renders through generic task_output. Spawn failures also pass through settlement, so confined background handles retain their mode/enforcement facts and release per-process accounting.ctx.sandboxPolicy (one home both enforcing families read), not this executor's config; resolve() stamps the default onto every spec, and an explicit request-level sandboxMode override — set by the tool layer only for a call whose wider mode a human granted through ctx.approval (the sandbox Agent Note § Escalation) — makes THAT call run, classify, and report under its own mode while every neighbor keeps the default (background facts are stamped per task at settle). The capability fact ctx.bash.sandboxMode reports the configured default so the tool layer advertises escalation only when this executor is mounted. The model learns of the sandbox only through result facts — the static bash tool description explains the denial marker; there is no current-mode statement in the system prompt.dsh-bash-local; runner selection lives in dsh-sandbox-local.Deny-only at the seam: a denial is a reported fact, and this executor never negotiates permissions itself — the approval question lives in the tool layer (dsh-tool-bash), which drives the override this package honors.
- 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()
- id: bash
name: '@deepseek-ai/dsh-bash-sandbox'
The keyless consumer-integration proofs are tests/bwrap.e2e.ts, tests/landlock.e2e.ts, and tests/seatbelt.e2e.ts (the real provider + real runner driven through ctx.bash, world-verified, each self-skipping where its runner is absent); see the acp-agent example's default composition for the runnable demo.
The generated dsh-tool-bash schemas are the baseline. By advertising a confining sandboxMode, this backend augments bash with sandbox_permissions using enum workspace-write | danger-full-access and with justification. The backend adds no prompt prose, and the session's effective mode remains unstated.
Small fixed schema increment on requests where bash is visible; mode switches add no context tokens.
Prefix-stable while the executor advertises the same sandbox capabilities. Changing those capabilities alters the bash schema and may invalidate reuse from that definition; per-session mode switches do not.
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 owned by dsh-sandbox. For an execution-time runner failure, this backend supplies the first stderr line as its detail.
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.
task_output.danger-full-access deliberately bypasses ctx.sandbox — it is an explicit unconfined mode, not a wider sandbox profile.