Skip to content

fix(shellwrap): capture login-shell PATH for docker credential helpers (#381)#382

Merged
Dumbris merged 1 commit intomainfrom
fix/381-shellwrap-minimalenv-path
Apr 11, 2026
Merged

fix(shellwrap): capture login-shell PATH for docker credential helpers (#381)#382
Dumbris merged 1 commit intomainfrom
fix/381-shellwrap-minimalenv-path

Conversation

@Dumbris
Copy link
Copy Markdown
Member

@Dumbris Dumbris commented Apr 11, 2026

Summary

  • Adds shellwrap.LoginShellPATH() — captures the user's login-shell PATH once per process (via sh -l -c 'printf %s "\$PATH"') and caches it.
  • MinimalEnv() now merges that login-shell PATH with the ambient PATH (login-shell entries first, deduped), so scanner subprocesses can resolve docker credential helpers (e.g. docker-credential-desktop) even when mcpproxy was started from a LaunchAgent / macOS App Bundle with a minimal PATH.
  • Windows behavior is unchanged (login-shell PATH capture is Unix-only).
  • Full fallback to ambient PATH when the login shell cannot be executed.

Fixes #381.

Why

ResolveDockerPath() already works around the LaunchAgent PATH problem for the docker binary itself, but docker pull was still failing on registries configured with credential helpers:

failed to pull ghcr.io/aquasecurity/trivy:latest: ... error getting credentials -
err: exec: "docker-credential-desktop": executable file not found in $PATH

That helper lives in /usr/local/bin or /opt/homebrew/bin — directories missing from the /usr/bin:/bin-style PATH that mcpproxy inherits when launched from a GUI. The docker CLI re-execs the helper via its own $PATH lookup, so the fix has to flow through cmd.Env, not exec.LookPath.

Test plan

  • go test -race ./internal/shellwrap/ (new tests cover merge-dedup, successful capture via fake \$SHELL, and fallback when the shell is broken)
  • go test -race ./internal/security/scanner/
  • go build ./... + go build -tags server ./...
  • golangci-lint run ./internal/shellwrap/...
  • Smoke test: with ambient PATH=/usr/bin:/bin, MinimalEnv() now returns PATH enriched with /opt/homebrew/bin, /usr/local/bin, etc.

🤖 Generated with Claude Code

… resolve

When mcpproxy runs as a macOS App Bundle or LaunchAgent, os.Getenv("PATH")
is often `/usr/bin:/bin`. shellwrap.ResolveDockerPath already works around
that for the docker binary itself by caching an absolute path from the
user's login shell, but `docker pull` still fails for registries that
need credential helpers (e.g. docker-credential-desktop), because the
docker CLI re-execs the helper via its own PATH lookup — and the helper
lives in /usr/local/bin or /opt/homebrew/bin, which are absent from the
ambient launchd PATH.

This adds a new LoginShellPATH() helper that captures the login shell's
PATH once per process via `sh -l -c 'printf %s "$PATH"'` and caches it.
MinimalEnv() now merges that login-shell PATH with the ambient PATH
(login-shell first, deduped) so subprocesses spawned by the scanner can
locate credential helpers and other developer tools. Ambient behavior is
fully preserved on Windows and in the success-path fallback when the
login shell cannot be executed.

Fixes #381

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: d55f630
Status: ✅  Deploy successful!
Preview URL: https://6b809b86.mcpproxy-docs.pages.dev
Branch Preview URL: https://fix-381-shellwrap-minimalenv.mcpproxy-docs.pages.dev

View logs

@github-actions
Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: fix/381-shellwrap-minimalenv-path

Available Artifacts

  • archive-darwin-amd64 (26 MB)
  • archive-darwin-arm64 (23 MB)
  • archive-linux-amd64 (15 MB)
  • archive-linux-arm64 (13 MB)
  • archive-windows-amd64 (25 MB)
  • archive-windows-arm64 (23 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (19 MB)
  • installer-dmg-darwin-arm64 (17 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 24286156026 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@Dumbris Dumbris merged commit e1c7e41 into main Apr 11, 2026
23 checks passed
@Dumbris Dumbris deleted the fix/381-shellwrap-minimalenv-path branch April 11, 2026 17:31
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.

Security Scanners fail to pull images because shellwrap.MinimalEnv() strips PATH required by Docker credential helpers

2 participants