dsh-sandbox-policy — the sandbox policy home (ctx.sandboxPolicy)
English | 中文
The single owner of sandbox-policy resolution: the deployment's default SandboxMode and fallback root, plus each session's durable mode override and immutable workspace root. Every enforcing family receives one resolved mode-and-root policy per call and registers whether the current runtime fences filesystem tools, one-shot bash commands, or terminal sessions; the model receives only those current facts before each request.
Why a shared home
Filesystem tools, one-shot bash commands, and terminal sessions may enforce the same mode vocabulary in different combinations. If each resolved its own mode + workspaceRoot, they could drift into a split world, exactly what the sandbox Agent Note warns against. Each enforcing backend consumes the complete owner-resolved policy and contributes its model-facing family; the current section therefore does not claim that an unfenced family shares another family's restrictions. The cross-family fs sandbox Agent Note records the shared-policy decision.
Config
mode— the deployment defaultSandboxMode(read-only/workspace-write/danger-full-access), validated at load. Defaultread-only(fail-safe).workspaceRoot— the fallback directoryworkspace-writemay write under for agentless calls or sessions without a cwd. Defaultprocess.cwd(), resolved to its absolute filesystem identity either way. A normal agent call uses its session header's immutablecwdinstead.
Surface
ctx.sandboxPolicy.resolve({ session?, mode? })— resolves one complete per-call policy. An explicit approved mode outranks the session's lastsandbox/modeevent, which outranksdefaultMode; the session's immutablecwdis canonicalized with filesystem semantics before becomingworkspaceRoot, otherwise the configured fallback applies. Canonicalization precedes lexical normalization sosymlink/..agrees with process working-directory resolution.ctx.sandboxPolicy.defaultMode/ctx.sandboxPolicy.workspaceRoot— the deployment default and fallback root used byresolve().ctx.sandboxPolicy.registerEnforcedFamily(family)— independently registersfilesystem,bash, orterminaland returns the exact effect disposer. Equal families remain separate contributions; the section uses canonical family order and removes a family only after its final contribution leaves.sandbox:policy— a request-time system-prompt section derived fromresolve({ session })and the active family contributions. It is empty without an enforcing family and states only the mode, the affected model-facing operations, and the canonical session workspace underworkspace-write.effectiveSandboxMode(events)— the pure fold of a session'ssandbox/modeevents (the last switch wins, orundefined), used insideresolve().setSandboxMode(session, mode)— THE write path for a per-session override: appends exactly onesandbox/modeevent. The switch IS its event; nothing mutates the mode out of band.SANDBOX_MODES— every mode, for option advertisement and runtime validation.
The optional ./invariant companion rejects a forged durable sandbox/mode event whose value falls outside that closed vocabulary; Session and its companion own the surrounding storage and core execution-enclosure rules. The rendered section is logged inside request/header, so the exact effective policy remains reconstructable without another event or an in-memory “last told” mirror.
The per-session store
A runtime switch is one log-only sandbox/mode event on the session it applies to. effective = explicit grant ?? fold(events) ?? deployment default, so an override survives restart by replay and two sessions never see each other's state. Workspace identity does not need another event: the immutable SessionHeader.cwd recorded at creation is the root for every call in that session. The event stays log-only; the next request assembles the current section from the fold before any tool call.
Model Experience
Current file sandbox policy
What the model sees
One sandbox:policy system section on each agent request when at least one enforcing family is registered. The examples below show all three families; absent families are omitted. Tool plugins retain operation and escalation guidance, approval policy remains dsh-user-approval's section, and plan guidance remains dsh-plan-mode's section.
Read-only
Current DSH file policy: read-only. The write and edit tools, one-shot bash commands, and terminal sessions cannot modify files under this policy.
Workspace-write
Current DSH file policy: workspace-write. The write and edit tools, one-shot bash commands, and terminal sessions may modify files under the session workspace: "<workspace root>". Some platform temporary areas may also be writable.
Danger-full-access
Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict the write and edit tools, one-shot bash commands, or terminal sessions.
Token effect
One concise system section per request. workspace-write carries only the canonical session workspace path; platform-specific temporary paths are summarized without adding host-dependent bytes.
KV Cache effect
The request prefix is byte-stable while the session mode and immutable workspace root stay unchanged. A mode switch changes the section on the next request; the resulting request/header records the new prefix.
Known Limitations and Deferred Work
- One primary workspace root per session — policy resolves
SessionHeader.cwd; extra writable roots are not part ofSandboxExecutionPolicy. - File-effect modes only —
SandboxModegoverns file effects; network and process policy are outside its vocabulary, so no knob here restricts them. - Temporary areas are deliberately summarized — enforcing backends grant different platform temporary areas, which are selected after policy resolution and therefore cannot be enumerated truthfully in the standing section.