|
|
2 hónapja | |
|---|---|---|
| .. | ||
| src | 2 hónapja | |
| tests | 2 hónapja | |
| README.md | 2 hónapja | |
| package.json | 2 hónapja | |
| tsconfig.json | 2 hónapja | |
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) — the model-facing tool layer (dsh-tool-bash) is untouched; that swap is exactly what the seams exist for.
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. Execution is dsh-bash-local's verbatim — foreground results still carry sandbox: { mode, denied: false } (no enforcement: nothing was confined), background tasks 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).runnerFailureSignatures (the runner's own error prefix — also what the shell prints for a missing runner) means the sandbox itself broke and the command NEVER RAN; the check outranks denial classification because a runner's error text can contain denial words. The foreground path re-throws it as the structured fail-closed SANDBOX_UNAVAILABLE error, with the runner's first stderr line as the cause; a settled background task stamps task.sandbox.runnerFailed instead (no error channel remains after settle), which bash_output renders as its own marker.resolve() stamps it 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 RFC § 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; the runner ladder, probes, and the per-platform Landlock launcher packages live with 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: bash
name: '@deepseek-ai/dsh-bash-sandbox'
config:
mode: read-only
workspaceRoot: !!js process.cwd()
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 examples/sandbox-acp-agent for the runnable demo.