Sandbox & approval: auto / full-auto / never
Pick the right sandbox mode (auto / full-auto / never), read an approval card, understand the fail-closed design, and how sandbox sits orthogonal to plugin permission boundaries.
8 min read
What you'll learn
- Understand DSH sandbox's three modes (auto / full-auto / never)
- How approval requests render in the UI
- Pick the right mode for your workflow (dev debugging vs unattended long tasks vs strict review)
Version
Compatible with: dsh 0.1.1-rc.2 (compiled from official apps/cli/README + docs/user/guide/)
Three sandbox modes
Every DSH tool call flows through the sandbox. The sandbox.mode setting in your profile config picks the default:
| Mode | Trigger condition | UI behavior | Best for |
|---|---|---|---|
auto | Allows calls that match "inferred-safe" rules, otherwise prompts | occasional cards | everyday users |
full-auto | allows everything, no prompts | completely silent | unattended long tasks / CI |
never | every call prompts | always prompts | strict review / learning |
The mode can be set as the default in profile config or switched live in Web GUI via the "Sandbox" dropdown in the top bar.
Approval card anatomy
When a command needs human approval, the UI renders a card with:
- Tool name + arguments (e.g.
bash("curl -I https://api.example.com")) - File / network / process impact inference
- Three buttons: "Allow once", "Allow for session", "Deny"
- Triggering plugin name
See dsh-approve-for-me for the "approve-for-me / strict-review" GUI presets — the former delegates approvals to a lightweight model, the latter forces per-step human review.
Fail-closed by design
DSH sandbox defaults to fail-closed: approval decision fails, model timeout, parse error → always deny. This prevents the disaster scenario where a broken approval subsystem silently frees the model to run any command.
Practical implications:
- Don't set the approval-decision model with a very short timeout (e.g. 3s); network jitter would break every tool call
- When the approval subsystem (lightweight model) is unavailable, switch to
nevermode for manual review — don't try to "bypass" the sandbox
How sandbox relates to permission boundaries
Sandbox decides "do we ask?" — it doesn't decide "is this plugin allowed to do this?". Permission boundaries come from bundle declarations + Cordis service injection. The two are orthogonal:
- allowed + plugin has permission → command runs
- allowed + plugin lacks permission → error (plugin doesn't have service X)
- denied + plugin has permission → card rejected
- denied + plugin lacks permission → card rejected (missing permission is moot)
Troubleshooting
- "full-auto ran a command that shouldn't be approved": usually a plugin hooked the approval pipeline; check
dsh --profile X --dump-patchesfor patches injectingapproveservice - "never mode freezes the whole session": a single card can pick "Allow for session" to approve a whole category of similar commands
- "auto mode blocks obviously safe commands": relax the rule set in profile config; rule names live at
cordis.services.config.sandbox.rules
FAQ
Does the sandbox recognize npm install?
Yes. auto mode defaults npm install to "inferred-safe" (only modifies project node_modules + package.json); when there's no lockfile it escalates to "requires review".
Can it block curl?
Yes, and it does by default. Under full-auto, even curl requires a whitelist (configurable by the user). DSH is intentionally stricter than traditional agents here.