Repository navigation
feat: processes Prax starts never inherit its proxy credential - #255
Merged
Merged
Conversation
Once HTTPS_PROXY carries Prax's forward-proxy credential, every child — git, gh, uv, plugin subprocesses running third-party code — would inherit it and spend credentials as Prax. subprocess.Popen now hands children the proxy URL without it, or their own identity (CHILD_PROXY_URL). On by default: a no-op while the URL carries no credential. Idea from DeepSeek Harness's scrubbed child environments.
…lose the open forward proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Audit of the Prax↔secrets-proxy channel (2026-10-01; the table is in
docs/security/secrets-proxy.md)::8785model path127.0.0.1, and Prax never disables verification:8786forward proxyThe fix is to give every forward-proxy caller its own credential (prax-secrets-proxy #5 and #6). There's a catch:
HTTPS_PROXY=http://prax-prod:<token>@…is exported into Prax's environment, so every child would inherit it: git, gh, uv, and plugin subprocesses running third-party code.What
prax/services/child_env.py:subprocess.Popenhands every child its environment with the proxy URLs stripped of the credential. IfCHILD_PROXY_URLis set, children get that URL instead: their own identity (e.g.prax-tools), which egress rules can narrow.subprocess.run/check_outputand asyncio subprocesses.env=is cleaned too.CHILD_ENV_STRIP_PROXY_CREDENTIALSdefaults to on. That is deliberate: it is a no-op while the proxy URL carries no credential, which is every deployment today, so it preserves prior behaviour. Once a token is set, off means leaking it.Verified
Live, with real
git ls-remote https://github.com/praxagent/praxrun as a child of a parent holdingprax-prod's credential, through an authenticating mitmproxy (prax-secrets-proxy #6 code):prax-toolsTests: 7 unit tests (stripping, explicit env, own identity, no-op without credentials, asyncio, idempotent install).
make cigreen: 4017 passed. Four secrets-proxy requests during the run were production's 19:00 scheduled job (3× OpenRouter, then Twilio, all at 02:00 UTC), not tests.Rollout (after proxy #5/#6 are deployed; production
.envis yours)prax-prod,prax-devand, if children need egress,prax-tools.PROXY_FORWARD_AUTH_TOKEN/PROXY_FORWARD_CALLERSon the proxy.HTTPS_PROXY=http://prax-prod:<token>@127.0.0.1:8786in production andprax-devin dev, plus optionallyCHILD_PROXY_URL.curl -x http://127.0.0.1:8786 http://probe.invalid/must return 407.