feat(sandbox): alias/runtime sandbox defaults and persistent network allowlist#2888
Open
dgageot wants to merge 8 commits into
Open
feat(sandbox): alias/runtime sandbox defaults and persistent network allowlist#2888dgageot wants to merge 8 commits into
dgageot wants to merge 8 commits into
Conversation
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
aheritier
reviewed
May 23, 2026
This comment was marked as low quality.
This comment was marked as low quality.
Aliases declared in ~/.config/cagent/config.yaml can now carry a sandbox flag. When set, 'docker agent run <alias>' takes the sandbox path automatically without needing --sandbox on the command line. The flag joins yolo, model, and hide_tool_results in Alias and is exposed via 'docker agent alias add --sandbox'. An explicit --sandbox=false on the command line still wins, matching the precedence other alias options follow.
Agent authors can now declare a sandbox default in the YAML itself:
runtime:
sandbox: true
Any caller of the agent then takes the sandbox path automatically,
without having to remember --sandbox. An explicit --sandbox=false on
the CLI still wins, matching the precedence aliases follow.
This is the per-agent counterpart of the per-alias sandbox flag, and
is especially useful for catalog agents that always need filesystem
or network isolation.
Adds the new RuntimeDefaults block to the latest config schema, the
matching JSON schema definition, and a refreshed sandbox_agent.yaml
example demonstrating the feature.
Agents that talk to endpoints the auto-installer can't infer (custom
MCP servers, third-party APIs, registries not covered by the aqua
resolver, ...) saw a default-deny 403 from the sandbox proxy on
first contact, then had to fall back to the wider conservative host
union the kit uses on resolution failures.
Let agent authors declare those hosts explicitly:
runtime:
sandbox: true
network_allowlist:
- api.example.com
- registry.npmjs.org
The list is unioned with the gateway and tool-install hosts the
runner already opens automatically and printed before launch so
users can audit exactly which holes the run punched in the
default-deny policy. Commas and whitespace are rejected so a single
entry can't smuggle several rules into the policy engine.
Hosts the kit's per-toolset resolver can't infer (custom MCP endpoints, third-party APIs, registries not covered by aqua) showed up as a 403 from the sandbox proxy and forced the run to fall back to the wider conservative host union. Authors can now declare them in runtime.network_allowlist, but users running someone else's agent still had no easy fix. Add a persistent user-level allowlist plus three subcommands to manage it: docker agent sandbox allow <host> [<host>...] docker agent sandbox deny <host> docker agent sandbox list Entries land in ~/.config/cagent/config.yaml under sandbox_allowlist and are unioned with the gateway, the kit-resolved tool install hosts, and the agent-declared list on every subsequent --sandbox run. The launch summary now prints each source on its own line so it's clear which layer punched which hole, and the tool-install summary surfaces a hint pointing at 'sandbox allow' when the per-toolset resolver had to fall back. Commas and embedded whitespace are rejected at write time so a single entry can't smuggle several rules into the policy engine.
…aults The dispatch logic only checked !f.sandbox before consulting the alias and the agent's runtime.sandbox, so passing --sandbox=false on the CLI silently fell through to either of the lower-priority sources. The README and the schema both promise that the explicit flag wins, so detect whether the user actually set it via cmd.Flags().Changed and skip the override path in that case. Extract the precedence into resolveSandboxDefault so the rule is testable on its own, and add a regression test covering both the "flag not set" and "flag explicitly false" paths.
Threads the *latestcfg.Config loaded by resolveSandboxDefault through to runInSandbox so agentNetworkAllowlist no longer re-resolves and re-loads the same agent ref. For OCI-hosted agents this drops one network round-trip per sandboxed run. agentNetworkAllowlist now also drops entries with embedded commas or whitespace and warns: an agent YAML with 'a.example.com, b.example.com' as a single string used to feed a malformed value straight into the proxy policy, where the comma silently smuggled two rules into one. Narrows resolveSandboxDefault to take agentRef string instead of []string, dropping the implicit args[0] contract from the call site, and refreshes the misleading runOrExec comment on alias.Sandbox so it describes the post-decision state, not the side-effect.
Previously a batch like ('valid.example.com', 'bad,host.example.com')
appended the valid entry to SandboxAllowlist before bailing out on the
malformed one, leaving the in-memory *Config inconsistent with what
would have been persisted to disk. Validate every entry first, mutate
only when the whole batch is clean.
'sandbox deny <host>' used to error when the host was already absent, which is unusual for remove-style CLIs (docker rm --force, git branch -D, ...) and surprises scripts that don't pre-check membership. Now prints a notice and returns nil so 'deny' is safe to retry. Also strips user-supplied hostnames from the telemetry payload for allow / deny / list. Sandbox hosts often identify private corp endpoints (internal registries, VPN-only APIs); we still record the sub-command, but no longer the values.
1f4dbcc to
c8ef1af
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR makes sandbox enablement configurable from three new sources, and lets users curate a persistent network allowlist for hosts the kit's tool resolver can't infer (custom MCP servers, third-party APIs, registries not covered by aqua, ...).
Sandbox-by-default sources
Three new ways to opt an agent into the sandbox without typing
--sandbox:Aliases declared in
~/.config/cagent/config.yaml:Also exposed via
docker agent alias add --sandbox.Agent runtime config in the YAML itself:
Per-agent counterpart of the alias flag, useful for catalog agents that always need filesystem or network isolation.
An explicit
--sandbox=falseon the CLI still wins over both, matching the precedence the README and JSON schema already promise. The dispatch logic was previously falling through to the alias / runtime defaults when the user passed--sandbox=falsebecause it only checked!f.sandbox; it now consultscmd.Flags().Changed("sandbox")and the precedence is extracted into a testableresolveSandboxDefaulthelper.Network allowlist
Two coordinated additions to widen the default-deny proxy policy without sliding back to the conservative host union the kit falls back to on resolver failure:
Author-declared, per agent:
User-managed, persistent for hosts the agent author can't anticipate:
Entries land in
~/.config/cagent/config.yamlundersandbox_allowlistand are unioned on every subsequent--sandboxrun.Both lists are unioned with the gateway and the kit-resolved tool install hosts. Commas and embedded whitespace are rejected at write time so a single entry can't smuggle several rules into the policy engine. The launch summary now prints each source on its own line so it's clear which layer punched which hole, and the tool-install summary surfaces a hint pointing at
sandbox allowwhen the per-toolset resolver had to fall back.Files