fix(tools): reconcile docker_network with --network in docker_extra_args - #100256
Closed
davidkarban wants to merge 1 commit into
Closed
fix(tools): reconcile docker_network with --network in docker_extra_args#100256davidkarban wants to merge 1 commit into
davidkarban wants to merge 1 commit into
Conversation
`docker_network: false` made DockerEnvironment append `--network=none`, and
`docker_extra_args` was appended verbatim afterwards, with no reconciliation
between the two. Docker rejects a repeated `--network` outright ("network
"none" is specified multiple times"), so every container start for such a
profile failed with exit 125 and the Docker backend was unusable.
Resolve the two settings before building the command line:
- no network flag in docker_extra_args -> `--network=none`, as before
- `--network=none` in docker_extra_args -> emit the flag once
- any other network in docker_extra_args -> raise, naming both keys
The third case is contradictory intent rather than a duplicate. Letting the
extra arg win would hand the agent a networked container despite the
configured lockdown, and the cross-process reuse guard (which treats
NetworkMode != "none" as a mismatch) would then remove and recreate that
container on every startup. Failing closed and naming both keys is the only
outcome that neither weakens the lockdown nor churns containers.
The `{"--network", "--net"}` flag set becomes a module constant so the new
parser and the existing `_extra_args_egress_collisions()` share one
definition.
Tested on Linux (Ubuntu 24.04, Docker 29.5.2). The four new regression tests
fail on the unpatched tree and pass with the fix; `tests/tools/*docker*` plus
`tests/tools/test_terminal_tool.py` are green (150 passed).
Fixes NousResearch#100248
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ntht3XCLT5DKuvGrKQE7E
13 tasks
Contributor
This PR fixes a real bug: with
Verdict: LGTM |
Collaborator
|
Landed on |
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.
What does this PR do?
terminal.docker_network: falseandterminal.docker_extra_argsare independently documented and independently valid, but combining them was unconditionally fatal.DockerEnvironment.__init__appended--network=noneitself for the lockdown, then appendeddocker_extra_argsverbatim, with nothing reconciling the two. Docker rejects a repeated--network:Every
docker runfor such a profile exited 125 and the Docker backend was unusable until one of the two settings was removed.This reconciles them before the command line is built:
docker_networkdocker_extra_argsfalse--network=none— unchangedfalse--network=nonelogger.infofalse--network=host/ named netRuntimeErrornaming both keysWhy the third row raises instead of letting the extra arg win
"Extra args are appended last so they can override defaults" is the natural reading, and it is what #100248's original Proposed Fix suggested. Implementing it showed that it is wrong here, because of the cross-process reuse guard:
Under override semantics,
docker_network: false+--network=hostwould hand the agent a host-networked container despite the configured lockdown, and the guard would then remove and recreate that container on every startup, since its NetworkMode is permanentlyhostand nevernone. A silent weakening of the lockdown plus unbounded container churn.Those two settings genuinely contradict, so the honest resolution is to say so. This also matches the posture the module already takes next door —
_extra_args_egress_collisions()raises rather than guessing whenenforce_on_dockeris set.The
{"--network", "--net"}flag set is lifted to a module constant so the new parser and the existing collision helper share a single definition.How to test
Reduced to plain Docker, this is the exact shape
all_run_argsproduced:Through Hermes:
Before: every sandbox creation fails with exit 125. After: the container starts,
--network=noneappears once, and--user 1009:1009is applied.Automated:
The four new tests fail on the unpatched tree (verified by reverting only
tools/environments/docker.pyand re-running) and pass with the fix.test_lockdown_still_applies_without_extra_network_argis the no-regression guard for the common case, and passes either way.New coverage:
--network=nonein extra args → flag emitted exactly once--network none→ same--network=nonestill emitted--network=host→ raises--netaliases,=and space forms, non-string entries, and a trailing bare--networkthat must notIndexErrorPlatforms tested
Linux (Ubuntu 24.04, Docker 29.5.2, Python 3.11.15). The change is pure argument-list construction with no platform-specific behaviour.
Related issue
Fixes #100248.
Note for reviewers: that issue's Proposed Fix section describes the simple override semantics. I have commented there explaining why this PR uses the three-way split instead, so the issue and PR do not disagree.
Adjacent but deliberately not touched here, to keep this focused: #84027 (
file_tools/code_execution_tooldropdocker_extra_argsfrom theircontainer_config). The two interact badly in production — the exit 125 above kills the terminal-tool creation, then afile_toolscreation succeeds because it drops the extra args, silently yielding a container with the wrong uid. That is #84027's to fix (#35660 / #90050 are open for it).