feat(secureenv): opt-in proxy env forwarding to upstreams (MCP-2769)#704
Conversation
Split out of MCP-2751 login-shell hydration: forwarding HTTP(S)/proxy env vars to every stdio upstream by default leaks credential-bearing proxy URLs (http://user:pass@proxy). Keep proxy vars OUT of the default allow-list and gate forwarding behind an explicit opt-in. - config: new global `forward_proxy_env` (default false). - secureenv: when opted in, BuildSecureEnvironment forwards the ambient proxy vars (HTTP_PROXY/HTTPS_PROXY/NO_PROXY/ALL_PROXY/FTP_PROXY, both upper- and lower-case spellings) to spawned stdio upstreams. userinfo (credentials) is redacted from each value; the proxy host/port is preserved. Case-alias aware: an explicitly configured spelling suppresses forwarding of the ambient alias. Forwarding is independent of inherit_system_safe. - upstream/core: thread the flag into the per-server env config for stdio spawns. - docs/configuration.md: document the opt-in + the never-by-default rationale. Tests: redaction unit table, default-off leak guard, opt-in redacted forward, explicit-wins-over-alias, and an end-to-end wiring test through managed.NewClient. Related #701
Deploying mcpproxy-docs with
|
| Latest commit: |
231497a
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://06cabd46.mcpproxy-docs.pages.dev |
| Branch Preview URL: | https://mcp-2769-forward-proxy-env.mcpproxy-docs.pages.dev |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
📦 Build ArtifactsWorkflow Run: View Run Available Artifacts
How to DownloadOption 1: GitHub Web UI (easiest)
Option 2: GitHub CLI gh run download 27687831433 --repo smart-mcp-proxy/mcpproxy-go
|
🤖 Codex review — REQUEST_CHANGES (1×P2, security)[P2] Redact schemeless proxy credentials before forwarding —
|
…2769) Codex PR #704 review (P2, security): redactProxyCredentials missed schemeless proxy values like "user:pass@proxy:8080" (no scheme). url.Parse reads "user" as the scheme and leaves Userinfo nil, so the original credential-bearing value was forwarded to upstreams despite the redaction guarantee. Fix: when the value has no "://" but contains "@", re-parse with a dummy "http://" scheme so url.Parse recognizes the userinfo, strip it, then remove the dummy scheme. An "@" inside a path (host/path@x) keeps Userinfo nil and is left intact. Adds table cases (schemeless user:pass / user-only / no-userinfo / at-in-path) and an end-to-end forwarding test asserting no creds reach upstream. Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
Fixed in 231497a — thanks, this was a real leak.
Tests added:
|
✅ Review (Claude Code, Codex rate-limited) — ACCEPTRigorous substitute review while Codex is rate-limited (per maintainer direction). Previously-flagged P2 (schemeless credential redaction) — CONFIRMED RESOLVED. Opt-in correctness ✓ — Security ✓ — no raw-value logging, no un-redacted forward path. Tests ✓ — Non-blocking (optional hardening, not gating): a proxy value with surrounding whitespace ( VERDICT: ACCEPT |
…P-2776) (#705) Follow-up to PR #704 (MCP-2769) reviewer note: redactProxyCredentials did not trim surrounding whitespace, so a value like " http://user:pass@proxy " made url.Parse error (leading space) and fall through, forwarding the credentialed value verbatim and bypassing the redaction guarantee. Trim whitespace at function entry before parsing; whitespace is never meaningful in a proxy URL. Adds table cases for whitespace-wrapped scheme'd and schemeless credentialed values. Co-authored-by: Paperclip <noreply@paperclip.ing>
Summary
Split out of MCP-2751 (login-shell hydration). Codex flagged that adding
HTTP_PROXY/HTTPS_PROXYto the secureenv default allow-list would forward credential-bearing proxy URLs (http://user:pass@proxy) to every stdio upstream on all platforms. This PR keeps proxy vars out of the default allow-list and makes forwarding an explicit, credential-redacting opt-in.Behavior
forward_proxy_env(defaultfalse). Current behavior is unchanged when unset.true,secureenv.BuildSecureEnvironmentforwards the ambient proxy variables to spawned stdio upstreams:HTTP_PROXY,HTTPS_PROXY,NO_PROXY,ALL_PROXY,FTP_PROXY— both upper- and lower-case spellings (case-alias aware).http://user:pass@proxy:8080→http://proxy:8080); the proxy host/port is preserved.custom_varsor a server'senv) wins and suppresses forwarding of the ambient value, including the other-cased alias.inherit_system_safe(it is its own explicit opt-in).Files
internal/config/config.go—forward_proxy_envflag.internal/secureenv/manager.go— forwarding +redactProxyCredentials.internal/upstream/core/client.go— thread flag into per-server stdio env.docs/configuration.md— opt-in docs + never-by-default rationale.oas/*— regenerated (config is a documented model).Tests
redactProxyCredentialstable (user:pass, user-only, socks, host-list, unparseable).NO_PROXYpasses unchanged.managed.NewClient.Verification
Related #701