fix(yolo): drop sandbox to DangerFullAccess — no guardrails as advertised

User report: YOLO mode was still routing shell commands through the
WorkspaceWrite sandbox, which intercepted legitimate outside-workspace
writes (package installs, sub-agent workspaces, package-manager state
under ~/.cache, brew, npm install -g, pipx, …) and forced approval
round-trips. That contradicts the YOLO contract — the user opted into
"no guardrails" and instead got a guardrail.

YOLO already auto-approves all tools and enables trust mode. The
sandbox was the last residual restriction. Drop it.

Change in `Engine::build_tool_context`: split the previously-merged
`AppMode::Agent | AppMode::Yolo` arm into two:

* **Agent** keeps `WorkspaceWrite { writable_roots, network_access:
  true, … }` — interactive mode with explicit per-tool approval, so
  the sandbox plus the approval flow form a defense-in-depth layer.
* **Yolo** uses `DangerFullAccess` — no sandbox. The user has
  opted into auto-approval + trust mode + no sandbox as one
  consistent posture.

Plan mode unchanged (read-only, no shell tool registered).

Updated `agent_and_yolo_modes_elevate_shell_sandbox_to_allow_network`
to pin the new YOLO contract: `DangerFullAccess` specifically, not
just "has network access."

Verified locally:

* `cargo fmt --all -- --check` clean.
* `cargo clippy --workspace --all-targets --all-features --locked
  -- -D warnings` clean.
* `cargo test --workspace --all-features --locked` — green
  (the snapshot::repo flake still flakes in batch but passes in
  isolation; unrelated).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hunter Bown
2026-05-04 23:37:20 -05:00
parent 5c72e5f463
commit 4c783be52d
2 changed files with 32 additions and 12 deletions
+19 -7
View File
@@ -1294,13 +1294,14 @@ impl Engine {
// registered, so leaving the sandbox policy at the seatbelt-strict
// default is fine.
AppMode::Plan => ctx,
// Agent and Yolo both register the shell tool. The sandbox-default
// policy denies all outbound network — including DNS — which
// breaks ordinary developer commands (cargo fetch, npm install,
// curl, yt-dlp, …) without buying the user any safety the
// application-level NetworkPolicy / approval flow doesn't already
// provide. Elevate to workspace-write + network. (#273)
AppMode::Agent | AppMode::Yolo => {
// Agent registers the shell tool and runs each command through
// the per-mode sandbox + per-tool approval flow. The sandbox
// default would deny all outbound network — including DNS —
// which breaks ordinary developer commands (cargo fetch, npm
// install, curl, yt-dlp, …) without buying the user any safety
// the approval flow doesn't already provide. Elevate to
// workspace-write + network. (#273)
AppMode::Agent => {
ctx.with_elevated_sandbox_policy(crate::sandbox::SandboxPolicy::WorkspaceWrite {
writable_roots: vec![self.session.workspace.clone()],
network_access: true,
@@ -1308,6 +1309,17 @@ impl Engine {
exclude_slash_tmp: false,
})
}
// YOLO is the explicit "no guardrails" mode — auto-approve all
// tools, trust mode on, no sandbox. Workspace-write was still
// intercepting commands that wanted to write outside the
// workspace (rare but legitimate: pipx install, npm install
// -g, brew, package-manager state under ~/.cache, sub-agent
// workspaces, …) which forced approval round-trips and
// contradicts the YOLO contract. The user opted into YOLO
// deliberately; trust them.
AppMode::Yolo => {
ctx.with_elevated_sandbox_policy(crate::sandbox::SandboxPolicy::DangerFullAccess)
}
}
}
+13 -5
View File
@@ -390,12 +390,20 @@ fn agent_and_yolo_modes_elevate_shell_sandbox_to_allow_network() {
);
let yolo_ctx = engine.build_tool_context(AppMode::Yolo, false);
let yolo_policy = yolo_ctx
.elevated_sandbox_policy
.as_ref()
.expect("Yolo mode should elevate the sandbox policy");
assert!(yolo_policy.has_network_access());
// v0.8.11: YOLO drops to DangerFullAccess (no sandbox) so the user
// is not bounced through approval round-trips for legitimate
// outside-workspace writes (package installs, sub-agent
// workspaces, ~/.cache mutations, etc.). YOLO is opt-in and
// already enables trust mode + auto-approve; the sandbox was the
// last guardrail and contradicts the contract.
assert!(
yolo_ctx
.elevated_sandbox_policy
.as_ref()
.expect("Yolo mode should elevate the sandbox policy")
.has_network_access(),
matches!(yolo_policy, crate::sandbox::SandboxPolicy::DangerFullAccess),
"Yolo mode must use DangerFullAccess (no sandbox); got {yolo_policy:?}",
);
// Plan mode is read-only investigation and does not register the shell