Skip to content

fix(docker): pass env values to docker via environment, not -e KEY=VALUE argv - #1811

Merged
github-actions[bot] merged 3 commits into
mainfrom
claude/issue-1809-fix-review-cae3fe
Nov 1, 2026
Merged

github-actions[bot] merged 3 commits into
mainfrom
claude/issue-1809-fix-review-cae3fe

Conversation

@Dumbris

@Dumbris Dumbris commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Summary

For a stdio server whose command is docker run …, and for a server under Docker isolation, every entry of the server's env map was turned into a -e KEY=VALUE argument of the docker process. Resolved secrets (${keyring:…}, ${env:…}, ${file:…}) therefore sat in the process table, readable by every local user via ps aux or /proc/<pid>/cmdline.

Both spawn paths (connection_stdio.go, connection_launcher.go) already merge config.Env into the docker client's environment, so this change emits the key-only -e KEY form in injectEnvVarsIntoDockerArgs and the isolation BuildDockerArgs. The docker CLI takes the value from its own environment, which only the process owner and root can read. Keys are emitted in sorted order so argv and its log line are deterministic. An empty value still reaches the container as set-but-empty.

Closes #1809

Verification

  • New tests in internal/upstream/core/docker_env_argv_test.go cover the helper, the isolation builder, and the launcher direct-exec and shell-wrap paths (secret in cmd.Env, never in cmd.Args); existing assertions flipped from -e KEY=VALUE to -e KEY.
  • go test -race ./internal/upstream/core/ green; CI golangci-lint config clean apart from the pre-existing reflect.Ptr baseline finding.
  • Live run on an isolated instance with one isolated npx server and one user-supplied docker run server, both with a secret in env: ps axww shows only -e ISO_SECRET_1809 / -e USR_SECRET_1809, no value anywhere in argv; docker inspect on both containers shows the values (and ISO_EMPTY=) arrived.

Docs

docs/docker-isolation.md (Environment Variables) and docs/features/keyring-integration.md (file references) now state where an env value is and is not visible.

…LUE argv

For a stdio server whose command is `docker run …`, and for a server under
Docker isolation, every entry of the server's `env` map was turned into a
`-e KEY=VALUE` argument of the docker process. Resolved secrets (`${keyring:…}`,
`${env:…}`, `${file:…}`) therefore sat in the process table, readable by every
local user via `ps aux` or `/proc/<pid>/cmdline`.

Both spawn paths already merge `config.Env` into the docker client's
environment, so emit the key-only `-e KEY` form: the docker CLI takes the
value from its own environment, which only the owner and root can read.
Keys are emitted in sorted order so argv and its log line are deterministic.
An empty value still reaches the container as set-but-empty.

Closes #1809

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 2eef47e
Status: ✅  Deploy successful!
Preview URL: https://641aa0b4.mcpproxy-docs.pages.dev
Branch Preview URL: https://claude-issue-1809-fix-review.mcpproxy-docs.pages.dev

View logs

Dumbris and others added 2 commits November 1, 2026 12:11
…shell edge

Review round 1 (Sol 6.1): prependDockerDirToPath rewrites the docker client's
PATH after the config.Env merge, so a key-only `-e PATH` would forward the
host docker dir into a container whose PATH the user configured. PATH is
never a secret, so it stays `-e PATH=<value>`. The login-shell fallback
(docker not resolvable) lets a profile that exports the same name win; this
is documented in the helper and in docs/docker-isolation.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review round 2 (Sol 6.1): Windows spells the variable `Path`, so the inline
exception now matches case-insensitively and keeps the configured spelling.
The login-shell caveat also covers a resolved docker on Linux without
DOCKER_HOST/DOCKER_CONTEXT exported, not only an unresolvable docker.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

📦 Build Artifacts

Workflow Run: View Run
Branch: claude/issue-1809-fix-review-cae3fe

Available Artifacts

  • archive-darwin-amd64 (32 MB)
  • archive-darwin-arm64 (29 MB)
  • archive-linux-amd64 (20 MB)
  • archive-linux-arm64 (18 MB)
  • archive-windows-amd64 (32 MB)
  • archive-windows-arm64 (28 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (28 MB)
  • installer-dmg-darwin-arm64 (25 MB)
  • smart-mcp-proxymcpproxy-goVSN42R.dockerbuild (0 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 41296613339 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved (Model B): Paperclip review verdicts = ACCEPT and qa-gate green at this head SHA. Arming auto-merge; GitHub merges when all required checks pass.

@github-actions
github-actions Bot enabled auto-merge (squash) November 1, 2026 10:29
@github-actions
github-actions Bot merged commit c9ad7bd into main Nov 1, 2026
49 checks passed
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docker stdio servers: env values (incl. resolved secrets) are passed as -e KEY=VALUE argv and visible in ps

2 participants