Docker file_tools container config missing cwd flags

NousResearch/hermes-agent · cluster 2672 · environments

Data as of

Nothing open on GitHub. Fix merged in #12900. Check it covers your case.

The short answer

0open issues
0open PRs
10items grouped
Known?
Yes. 10 related items grouped here, 2 issues already closed.
Fix event
A fix was merged to main in PR #12900. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PRs #12900, #54616. That is separate from the fix event.
Still open
Nothing open on GitHub.

Multiple reports and fix attempts address docker_mount_cwd_to_workspace and docker_forward_env not being passed to container_config in file_tools, plus a related issue of unsanitized host cwd reaching the container sandbox.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #12900 fix(docker): pass docker_mount_cwd_to_workspace and docker_forward_env to container_config in file_tools

    merged to main

    files: tests/tools/test_file_tools_container_config.py, tools/file_tools.py

  • #54616 fix(file-tools): sanitize host/relative cwd override before it reaches container sandbox (#54447)

    merged to main

    files: tests/tools/test_container_cwd_sanitize.py, tools/file_tools.py

    Show the diff
    • tests/tools/test_container_cwd_sanitize.py
      @@ -144,3 +144,114 @@ def test_valid_container_override_is_preserved(self, monkeypatch):
               # RL/benchmark envs set an in-container path; it must pass through.
               cwd = self._run_and_capture_cwd(monkeypatch, "/workspace/task42")
               assert cwd == "/workspace/task42"
      +
      +
      +class TestFileOpsCwdSanitizedAtCallSite:
      +    """E2E pin: file tools (_get_file_ops) must sanitize a host/relative cwd
      +    override before it reaches _create_environment on a container backend —
      +    the same guard the terminal tool got in #50636.  Without it, a Desktop/TUI
      +    host cwd (e.g. ``/Users/me/workspace``) leaks straight into
      +    ``docker run -w`` and ``search_files`` returns an empty workspace (#54447).
      +    """
      +
      +    def _run_and_capture_cwd(self, monkeypatch, override_cwd, env_type="docker",
      +                             config_cwd="/workspace"):
      +        """Drive ``_get_file_ops()`` on a container backend with a host-path cwd
      +        override registered, and return the cwd that reached
      +        ``_create_environment`` (i.e. the cwd passed to ``docker run -w``).
      +        """
      +        import tools.terminal_tool as tt
      +        import tools.file_tools as ft
      +
      +        captured = {}
      +
      +        config = {
      +            "env_type": env_type,
      +            "docker_image": "pytorch/pytorch:latest",
      +            "singularity_image": "docker://pytorch/pytorch:latest",
      +            "modal_image": "pytorch/pytorch:latest",
      +            "daytona_image": "pytorch/pytorch:latest",
      +            "cwd": config_cwd,
      +            "host_cwd": None,
      +            "timeout": 180,
      +            "lifetime_seconds": 300,
      +            "container_cpu": 1,
      +            "container_memory": 5120,
      +            "container_disk": 51200,
      +            "container_persistent": True,
      +            "docker_volumes": [],
      +            "docker_env": {},
      +            "docker_extra_args": [],
      +            "docker_mount_cwd_to_workspace": False,
      +            "docker_run_as_host_user": False,
      +            "docker_forward_env": [],
      +            "modal_mode": "auto",
      +            "ssh_host": "",
      +            "ssh_user": "",
      +            "ssh_port": 22,
      +            "ssh_key": "",
      +            "ssh_persistent": False,
      +            "local_persistent": False,
      +        }
      +
      +        class _DummyEnv:
      +            cwd = config_cwd
      +
      +            def execute(self, *a, **k):
      +                return {"output": "", "exit_code": 0}
      +
      +        def fake_create_environment(env_type, image, cwd, timeout, **kwargs):
      +            captured["cwd"] = cwd
      +            return _DummyEnv()
      +
      +        monkeypatch.setattr(tt, "_get_env_config", lambda: config)
      +        monkeypatch.setattr(tt, "_start_cleanup_thread", lambda: None)
      +        monkeypatch.setattr(tt, "_create_environment", fake_create_environment)
      +        # Force a fresh environment build.
      +        monkeypatch.setattr(tt, "_active_environments", {})
      +        monkeypatch.setattr(tt, "_last_activity", {})
      +        monkeypatch.setattr(ft, "_file_ops_cache", {})
      +        monkeypatch.setattr(ft, "_last_known_cwd", {})
      +
      +        task_id = "sess-fileops-host-cwd"
      +        tt.register_task_env_overrides(task_id, {"cwd": override_cwd})
      +        try:
      +            ft._get_file_ops(task_id)
      +        finally:
      +            tt.clear_task_env_overrides(task_id)
      +        return captured.get("cwd")
      +
      +    def test_macos_host_override_does_not_reach_container(self, monkeypatch):
      +        # Desktop/TUI registers /Users/<me>/workspace as the session cwd.
      +        cwd = self._run_and_capture_cwd(monkeypatch, "/Users/me/workspace")
      +        assert cwd == "/workspace", (
      +            f"Host-path cwd override leaked to the container builder: {cwd!r}. "
      +            "It must be sanitized back to config['cwd']."
      +        )
      +
      +    def test_posix_home_host_override_does_not_reach_container(self, monkeypatch):
      +        cwd = self._run_and_capture_cwd(monkeypatch, "/home/someuser/project")
      +        assert cwd == "/workspace"
      +
      +    def test_windows_host_override_does_not_reach_container(self, monkeypatch):
      +        cwd = self._run_and_capture_cwd(monkeypatch, r"C:\Users\someuser")
      +        assert cwd == "/workspace"
      +
      +    def test_relative_cwd_override_does_not_reach_container(self, monkeypatch):
      +        cwd = self._run_and_capture_cwd(monkeypatch, "src/app")
      +        assert cwd == "/workspace"
      +
      +    def test_valid_container_override_is_preserved(self, monkeypatch):
      +        # RL/benchmark envs set an in-container path; it must pass through.
      +        cwd = self._run_and_capture_cwd(monkeypatch, "/workspace/task42")
      +        assert cwd == "/workspace/task42"
      +
      +    def test_host_override_sanitized_on_singularity(self, monkeypatch):
      +        cwd = self._run_and_capture_cwd(
      +            monkeypatch, "/Users/me/workspace", env_type="singularity")
      +        assert cwd == "/workspace"
      +
      +    def test_host_override_sanitized_on_modal(self, monkeypatch):
      +        cwd = self._run_and_capture_cwd(
      +            monkeypatch, "/Users/me/workspace", env_type="modal")
      +        assert cwd == "/workspace"
    • tools/file_tools.py
      @@ -832,6 +832,8 @@ def _get_file_ops(task_id: str = "default") -> ShellFileOperations:
               _creation_locks,
               _creation_locks_lock,
               _resolve_container_task_id,
      +        _is_unusable_container_cwd,
      +        _CONTAINER_BACKENDS,
           )
           import time
       
      @@ -893,6 +895,26 @@ def _get_file_ops(task_id: str = "default") -> ShellFileOperations:
                       image = ""
       
                   cwd = overrides.get("cwd") or _last_known_cwd.get(task_id) or config["cwd"]
      +            # Re-apply the container cwd guard that _get_env_config() already
      +            # ran on config["cwd"] (see #50636).  A per-task cwd override
      +            # registered by the gateway/TUI/ACP for workspace tracking is a
      +            # raw host path (e.g. a Desktop session's /Users/<me>/workspace or
      +            # C:\\Users\\<me>). On a container backend that reaches
      +            # ``docker run -w <host-path>`` and the container starts in a
      +            # directory that doesn't exist inside the sandbox, so search_files
      +            # and friends silently return empty results (#54447).  Sanitize it
      +            # back to the already-validated config["cwd"] so the override can't
      +            # bypass the guard.  Valid in-container override paths (RL/benchmark
      +            # sandboxes that set cwd to /workspace, /root, etc.) are absolute
      +            # non-host paths and pass through untouched.
      +            if env_type in _CONTAINER_BACKENDS and _is_unusable_container_cwd(cwd):
      +                if cwd != config["cwd"]:
      +                    logger.info(
      +                        "Ignoring host/relative cwd override %r for %s backend "
      +                        "(won't exist in sandbox). Using %r instead.",
      +                        cwd, env_type, config["cwd"],
      +                    )
      +                cwd = config["cwd"]
                   logger.info("Creating new %s environment for task %s...", env_type, task_id[:8])
       
                   container_config = None

6 PRs closed without merging

From the close comments: merged via another change 5 · done elsewhere 1

  • #2674 fix(file_tools): pass docker_mount_cwd_to_workspace to container_config · merged via another change → #12900
  • #2688 fix(docker): pass docker_mount_cwd_to_workspace and docker_forward_env to container_config in file_tools · done elsewhere → 2d59afd
  • #2697 fix: pass docker_mount_cwd_to_workspace to container_config in file_tools · merged via another change → #12900
  • #2729 fix(file_tools): pass docker_mount_cwd_to_workspace to container_config · merged via another change → #12900
  • #11888 fix: docker_mount_cwd_to_workspace missing from file_tools container_config · merged via another change → #12900
Show 1 more
  • #54474 fix(file-tools): sanitize host/relative cwd override before it reaches container sandbox (#54447) · merged via another change → #54616
Closed issues · 2
  • Closed#2672[Bug]: docker_mount_cwd_to_workspace config flag does not take effect in file tools
  • Closed#54447[Bug]: file tools build their Docker sandbox with an un-sanitized host cwd (search_files sees empty workspace); terminal-side fix #50636 left file_tools.py untouched
How this cluster was grouped
  • Link evidence (partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
  • Members outside that structural core may belong to a different underlying problem.
  • Pairwise link density 0.19: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
environments
Merged PRs
#12900, #54616
Closed issues
2
Attempts
6 PRs closed without merging
Fix link checked
29 Jun 2026

For your agent

The same facts, typed.