Skip to content

fix(file-safety): extend sandbox-mirror guard to cover inner-container path (#32049)#32407

Merged
benbarclay merged 3 commits into
NousResearch:mainfrom
whyhkzk:fix/docker-sandbox-mirror-inner-container
Jun 2, 2026
Merged

fix(file-safety): extend sandbox-mirror guard to cover inner-container path (#32049)#32407
benbarclay merged 3 commits into
NousResearch:mainfrom
whyhkzk:fix/docker-sandbox-mirror-inner-container

Conversation

@whyhkzk

@whyhkzk whyhkzk commented May 26, 2026

Copy link
Copy Markdown
Contributor

What

Extends the sandbox-mirror write guard from #32213 to cover the inner-container case — the primary failure mode in #32049.

Why

Brian's shape-based detector catches paths that still carry the full …/sandboxes/<backend>/<task>/home/.hermes/… prefix. But when file tools execute inside the container, the bind-mount strips that prefix: the guard receives plain /root/.hermes/… and passes through. The root:root ownership on the divergent SOUL.md in #32049 confirms this is what actually happened.

How

  • agent/file_safety.py — adds classify_container_mirror_target / get_container_mirror_warning as pure helpers that require an explicit mirror prefix. No long-lived ContextVar state.
  • tools/file_tools.py — detects the active or configured Docker persistent backend and passes /root/.hermes into the guard before creating file ops. This covers the first file-tool call, not only calls after DockerEnvironment already exists.
  • tests/agent/test_file_safety_container_mirror.py — covers the inner-container /root/.hermes/... path, non-Hermes paths, warning text, and the file-tool integration path before Docker environment creation.

Related

Builds on #32213. Both together fully cover #32049.


Reported-by: Diandian

…r path (NousResearch#32049)

Brian's shape-based guard (NousResearch#32213) catches paths that still carry the
full sandboxes/<backend>/<task>/home/.hermes/… prefix on the host side.
The inner-container case is not covered: when file tools execute inside
Docker the bind-mount strips that prefix, so the guard receives plain
/root/.hermes/… and passes through. The root:root ownership on the
divergent SOUL.md in NousResearch#32049 confirms this is the primary failure mode.

Add a ContextVar (_CONTAINER_HERMES_MIRROR) set by DockerEnvironment
when persistent=True. classify_container_mirror_target / get_container_
mirror_warning detect any write whose resolved path falls under that
prefix, using the same warning format and cross_profile=True bypass
contract as the existing guards. Chain the new guard in
_check_cross_profile_path after the two existing detectors.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent loop, run_agent.py, prompt builder tool/file File tools (read, write, patch, search) backend/docker Docker container execution labels May 26, 2026
# Conflicts:
#	agent/file_safety.py
#	tools/file_tools.py
@benbarclay benbarclay merged commit 1495f0c into NousResearch:main Jun 2, 2026
23 checks passed
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…r path (NousResearch#32049) (NousResearch#32407)

* fix(file-safety): extend sandbox-mirror guard to cover inner-container path (NousResearch#32049)

Brian's shape-based guard (NousResearch#32213) catches paths that still carry the
full sandboxes/<backend>/<task>/home/.hermes/… prefix on the host side.
The inner-container case is not covered: when file tools execute inside
Docker the bind-mount strips that prefix, so the guard receives plain
/root/.hermes/… and passes through. The root:root ownership on the
divergent SOUL.md in NousResearch#32049 confirms this is the primary failure mode.

Add a ContextVar (_CONTAINER_HERMES_MIRROR) set by DockerEnvironment
when persistent=True. classify_container_mirror_target / get_container_
mirror_warning detect any write whose resolved path falls under that
prefix, using the same warning format and cross_profile=True bypass
contract as the existing guards. Chain the new guard in
_check_cross_profile_path after the two existing detectors.

* fix(file-safety): derive Docker mirror guard from task

---------

Co-authored-by: Ben <ben@nousresearch.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend/docker Docker container execution comp/agent Core agent loop, run_agent.py, prompt builder P2 Medium — degraded but workaround exists tool/file File tools (read, write, patch, search) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants