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:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user