hermes - ✅(Solved) Fix Docker sandbox never receives env vars from docker_forward_env: missing keys in container_config [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#12534Fetched 2026-04-20 12:18:38
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
referenced ×2commented ×1cross-referenced ×1

On the docker terminal backend, environment variables listed in terminal.docker_forward_env (config.yaml) are never forwarded to the sandbox container. Agents running CLIs that depend on these vars (e.g. vercel, firebase, gh, etc.) fail with "no credentials" errors even though the vars are present in ~/.hermes/.env and correctly listed in the docker_forward_env whitelist.

Error Message

Actual: VT=0, vercel whoami fails with Error: No existing credentials found. This is silent: no warning, no error. Agents tasked with deployments, API calls or Git operations via CLI inside the sandbox appear to "not be authenticated" while the user believes the .env + docker_forward_env config is correct. Debugging requires reading sandbox source code.

Root Cause

In tools/terminal_tool.py, around line 1248, the container_config dict assembled for container backends (docker / singularity / modal / daytona) omits docker_forward_env and docker_env:

container_config = None
if env_type in ("docker", "singularity", "modal", "daytona"):
    container_config = {
        "container_cpu": config.get("container_cpu", 1),
        "container_memory": config.get("container_memory", 5120),
        "container_disk": config.get("container_disk", 51200),
        "container_persistent": config.get("container_persistent", True),
        "modal_mode": config.get("modal_mode", "auto"),
        "docker_volumes": config.get("docker_volumes", []),
        "docker_mount_cwd_to_workspace": config.get("docker_mount_cwd_to_workspace", False),
        # ❌ docker_forward_env and docker_env are MISSING here
    }

Then at line 707, build_environment reads cc.get("docker_forward_env", []) — which always returns [] because the key was never passed in — and instantiates DockerEnvironment(forward_env=[]).

As a result, _build_init_env_args() iterates over an empty forward_keys set and no -e KEY=VALUE flags are generated for the init_session docker exec, so the env snapshot captured by export -p never contains the user's whitelisted vars.

Confirmed via debug prints:

[HERMES-DEBUG] build_env: env_type=docker cc_keys=['container_cpu', 'container_disk', 'container_memory', 'container_persistent', 'docker_env', 'docker_forward_env', 'docker_mount_cwd_to_workspace', 'docker_volumes', 'modal_mode'] cc_fwd_len=0 TERMINAL_DOCKER_FORWARD_ENV=["GITHUB_TOKEN", ...]
[HERMES-DEBUG] _build_init_env_args: forward_keys_count=0 exec_env_count=0 os_environ_has_VERCEL_TOKEN=True

Note os.environ has the token (dotenv/bridge loaded it correctly), but forward_keys_count=0 because the list never made it into container_config.

Fix Action

Fix / Workaround

Tested locally — after applying this patch, the vars flow correctly from .envos.environdocker_forward_env list → -e flags at init_session → shell snapshot → agent commands.

PR fix notes

PR #12825: fix(docker): forward configured environment variables to sandbox containers

Description (problem / solution / changelog)

What changed

Environment variables listed in docker_forward_env config are now forwarded to sandbox containers at creation time via docker run -e, in addition to the existing docker exec -e forwarding during init_session().

Before: The docker_forward_env config keys were read but never injected into the container's native environment. Only _build_init_env_args() forwarded them via docker exec, which made vars visible only to bash subprocesses — not to processes started via docker run or inspectable via docker inspect.

After: Forwarded env vars are available in the container from the moment of creation, visible to all processes and inspectable via docker inspect. The two mechanisms serve distinct purposes:

  • docker run -e — persistent, visible to all processes in the container
  • docker exec -e — session-scoped, visible only to the init subprocess

How to test

  1. Add env vars to docker_forward_env in config.yaml:
    docker_forward_env:
      - MY_API_KEY
  2. Set MY_API_KEY=secret in your host .env
  3. Start a Docker sandbox and verify the var is available:
    docker inspect <container> | grep MY_API_KEY
  4. Run the test suite:
    pytest tests/tools/test_docker_forward_env.py -v

Platforms tested

  • Linux (Docker container, Python 3.11)

Closes #12534

Changed files

  • tests/tools/test_docker_forward_env.py (added, +190/-0)
  • tools/environments/docker.py (modified, +8/-0)

Code Example

VERCEL_TOKEN=vcp_xxxxxxxxx
   VERCEL_ORG_ID=xxxxxxxx

---

terminal:
     backend: docker
     docker_forward_env:
       - VERCEL_TOKEN
       - VERCEL_ORG_ID
       - GITHUB_TOKEN
       # ...etc

---

echo "VT=${#VERCEL_TOKEN}"
   vercel whoami

---

container_config = None
if env_type in ("docker", "singularity", "modal", "daytona"):
    container_config = {
        "container_cpu": config.get("container_cpu", 1),
        "container_memory": config.get("container_memory", 5120),
        "container_disk": config.get("container_disk", 51200),
        "container_persistent": config.get("container_persistent", True),
        "modal_mode": config.get("modal_mode", "auto"),
        "docker_volumes": config.get("docker_volumes", []),
        "docker_mount_cwd_to_workspace": config.get("docker_mount_cwd_to_workspace", False),
        # ❌ docker_forward_env and docker_env are MISSING here
    }

---

[HERMES-DEBUG] build_env: env_type=docker cc_keys=['container_cpu', 'container_disk', 'container_memory', 'container_persistent', 'docker_env', 'docker_forward_env', 'docker_mount_cwd_to_workspace', 'docker_volumes', 'modal_mode'] cc_fwd_len=0 TERMINAL_DOCKER_FORWARD_ENV=["GITHUB_TOKEN", ...]
[HERMES-DEBUG] _build_init_env_args: forward_keys_count=0 exec_env_count=0 os_environ_has_VERCEL_TOKEN=True

---

--- a/tools/terminal_tool.py
+++ b/tools/terminal_tool.py
@@ -1247,6 +1247,8 @@
                     container_config = {
                         "container_cpu": config.get("container_cpu", 1),
                         "container_memory": config.get("container_memory", 5120),
                         "container_disk": config.get("container_disk", 51200),
                         "container_persistent": config.get("container_persistent", True),
                         "modal_mode": config.get("modal_mode", "auto"),
                         "docker_volumes": config.get("docker_volumes", []),
                         "docker_mount_cwd_to_workspace": config.get("docker_mount_cwd_to_workspace", False),
+                        "docker_forward_env": config.get("docker_forward_env", []),
+                        "docker_env": config.get("docker_env", {}),
                     }
RAW_BUFFERClick to expand / collapse

Summary

On the docker terminal backend, environment variables listed in terminal.docker_forward_env (config.yaml) are never forwarded to the sandbox container. Agents running CLIs that depend on these vars (e.g. vercel, firebase, gh, etc.) fail with "no credentials" errors even though the vars are present in ~/.hermes/.env and correctly listed in the docker_forward_env whitelist.

Environment

  • Hermes version: v0.10.0 (2026.4.16) — commit 3b69b2fd
  • OS: Ubuntu 25.04 (x86_64)
  • Backend: terminal.backend: docker, container_persistent: true
  • Docker image: tested with both the default nikolaik/python-nodejs:python3.11-nodejs20 and a custom extension

Reproduction

  1. ~/.hermes/.env contains:

    VERCEL_TOKEN=vcp_xxxxxxxxx
    VERCEL_ORG_ID=xxxxxxxx
  2. ~/.hermes/config.yaml contains:

    terminal:
      backend: docker
      docker_forward_env:
        - VERCEL_TOKEN
        - VERCEL_ORG_ID
        - GITHUB_TOKEN
        # ...etc
  3. Restart gateway (systemctl --user restart hermes-gateway.service).

  4. Inside a Hermes session, run:

    echo "VT=${#VERCEL_TOKEN}"
    vercel whoami

Expected: VT=60, vercel whoami succeeds.

Actual: VT=0, vercel whoami fails with Error: No existing credentials found.

Root cause

In tools/terminal_tool.py, around line 1248, the container_config dict assembled for container backends (docker / singularity / modal / daytona) omits docker_forward_env and docker_env:

container_config = None
if env_type in ("docker", "singularity", "modal", "daytona"):
    container_config = {
        "container_cpu": config.get("container_cpu", 1),
        "container_memory": config.get("container_memory", 5120),
        "container_disk": config.get("container_disk", 51200),
        "container_persistent": config.get("container_persistent", True),
        "modal_mode": config.get("modal_mode", "auto"),
        "docker_volumes": config.get("docker_volumes", []),
        "docker_mount_cwd_to_workspace": config.get("docker_mount_cwd_to_workspace", False),
        # ❌ docker_forward_env and docker_env are MISSING here
    }

Then at line 707, build_environment reads cc.get("docker_forward_env", []) — which always returns [] because the key was never passed in — and instantiates DockerEnvironment(forward_env=[]).

As a result, _build_init_env_args() iterates over an empty forward_keys set and no -e KEY=VALUE flags are generated for the init_session docker exec, so the env snapshot captured by export -p never contains the user's whitelisted vars.

Confirmed via debug prints:

[HERMES-DEBUG] build_env: env_type=docker cc_keys=['container_cpu', 'container_disk', 'container_memory', 'container_persistent', 'docker_env', 'docker_forward_env', 'docker_mount_cwd_to_workspace', 'docker_volumes', 'modal_mode'] cc_fwd_len=0 TERMINAL_DOCKER_FORWARD_ENV=["GITHUB_TOKEN", ...]
[HERMES-DEBUG] _build_init_env_args: forward_keys_count=0 exec_env_count=0 os_environ_has_VERCEL_TOKEN=True

Note os.environ has the token (dotenv/bridge loaded it correctly), but forward_keys_count=0 because the list never made it into container_config.

Proposed fix

--- a/tools/terminal_tool.py
+++ b/tools/terminal_tool.py
@@ -1247,6 +1247,8 @@
                     container_config = {
                         "container_cpu": config.get("container_cpu", 1),
                         "container_memory": config.get("container_memory", 5120),
                         "container_disk": config.get("container_disk", 51200),
                         "container_persistent": config.get("container_persistent", True),
                         "modal_mode": config.get("modal_mode", "auto"),
                         "docker_volumes": config.get("docker_volumes", []),
                         "docker_mount_cwd_to_workspace": config.get("docker_mount_cwd_to_workspace", False),
+                        "docker_forward_env": config.get("docker_forward_env", []),
+                        "docker_env": config.get("docker_env", {}),
                     }

Tested locally — after applying this patch, the vars flow correctly from .envos.environdocker_forward_env list → -e flags at init_session → shell snapshot → agent commands.

Impact

This is silent: no warning, no error. Agents tasked with deployments, API calls or Git operations via CLI inside the sandbox appear to "not be authenticated" while the user believes the .env + docker_forward_env config is correct. Debugging requires reading sandbox source code.

Affected CLIs the community is likely to hit:

  • vercel (token-based auth)
  • firebase (GOOGLE_APPLICATION_CREDENTIALS)
  • gh (GITHUB_TOKEN)
  • Cloud SDKs relying on env-based auth (AWS, Supabase, Cloudflare, etc.)

Happy to open a PR with the 2-line fix + a regression test if useful.

extent analysis

TL;DR

Apply the proposed fix to tools/terminal_tool.py to include docker_forward_env and docker_env in the container_config dictionary.

Guidance

  • Review the container_config dictionary in tools/terminal_tool.py to ensure it includes docker_forward_env and docker_env.
  • Verify that the docker_forward_env list in config.yaml is correctly populated with the required environment variables.
  • Test the fix by running the reproduction steps and checking that the environment variables are correctly forwarded to the sandbox container.
  • Consider adding a regression test to prevent similar issues in the future.

Example

The proposed fix is a two-line change to tools/terminal_tool.py:

+                        "docker_forward_env": config.get("docker_forward_env", []),
+                        "docker_env": config.get("docker_env", {}),

This change ensures that the docker_forward_env and docker_env keys are included in the container_config dictionary.

Notes

The issue is specific to the docker backend and affects environment variables listed in terminal.docker_forward_env. The proposed fix is a targeted change to tools/terminal_tool.py and does not affect other parts of the codebase.

Recommendation

Apply the proposed fix to tools/terminal_tool.py to resolve the issue. This fix is a minimal change that addresses the root cause of the problem and has been tested locally.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix Docker sandbox never receives env vars from docker_forward_env: missing keys in container_config [1 pull requests, 1 comments, 2 participants]