feat(proxy): persistent proxy server (POC)#347
Conversation
…ommands Adds pmg proxy command group for running a long-lived MITM proxy that intercepts all package manager traffic without requiring PMG shims or wrappers. Targets CI/CD pipelines where env vars can be set globally. - pmg proxy start: starts proxy with npm+pypi interceptors, writes state file (pid/addr/ca-cert-path), auto-blocks suspicious packages - pmg proxy stop: sends SIGTERM to the running proxy - pmg proxy env: emits HTTP_PROXY/HTTPS_PROXY/SSL_CERT_FILE etc. as shell exports, or writes directly to $GITHUB_ENV with --gha - pmg proxy status: shows running/stopped status GHA usage: pmg proxy start & pmg proxy env --gha # populates env for all subsequent steps npm install # intercepted automatically, no wrapper needed Also adds .github/workflows/persistent-proxy-e2e.yml to validate the persistent proxy mode end-to-end in CI.
SafeDep Report SummaryNo dependency changes detected. Nothing to scan. This report is generated by SafeDep Github App |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #347 +/- ##
==========================================
+ Coverage 54.28% 54.57% +0.28%
==========================================
Files 184 197 +13
Lines 13131 13771 +640
==========================================
+ Hits 7128 7515 +387
- Misses 5324 5559 +235
- Partials 679 697 +18 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
pmg proxy stop now waits for the proxy process to exit, reads the final blocked count written to the state file on shutdown, and exits non-zero when one or more packages were blocked during the session. This gives CI a clear failure signal from the proxy itself, separate from the package manager's own exit code.
…cked Remove the if-wrapper that was swallowing the exit code. The step now fails naturally when stop exits 1, which is the correct CI behavior — a blocked package should fail the job.
| run: echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH | ||
|
|
||
| - name: Setup PMG | ||
| run: pmg setup install |
There was a problem hiding this comment.
Should we do --system here so that the certs are installed at the system level and we don't have to rely on environment for cert config? Would required sudo pmg setup install --system I think.
pmg proxy env can check if servers are installed as system level, if not, add the cert related env else skip it? Something like how PMG proxy flow works today.
Both cases work.
The reason I am kind leaning towards system installation is, in future we can "enforce" proxy via. iptables so that something like sudo npx x also works. Btw. sudo scrubs env so env based proxy config will not work if something is executed via. sudo
|
|
||
| - name: Start persistent proxy | ||
| run: | | ||
| pmg proxy start & |
There was a problem hiding this comment.
I would really prefer something like:
pmg proxy start --daemon | -D --state /custom/state/override
By default, pmg proxy start starts the proxy server as a foreground process. But --daemon can be used to daemonize the process, which has specific semantic on Linux/MacOS and Windows so, daemonize likely is a platform specific concern.
The default state storage can be cacheDir relative but user should be able to override it. Useful in CI setup where customization is useful.
| run: | | ||
| pmg proxy start & | ||
| # Poll until proxy writes its state file (up to 10s) | ||
| for i in $(seq 1 10); do |
There was a problem hiding this comment.
This is not required if we daemonize the proxy server.
| done | ||
|
|
||
| - name: Inject proxy env vars into workflow environment | ||
| run: pmg proxy env --gha |
There was a problem hiding this comment.
I think we are overloading concerns here. Its unnecessary coupling with CI env. It can be as simple as pmg proxy env which:
- Checks state file for port and anything else
- Prepares the env variables
- Prints the env variables
For GHA, I can just do: echo $(pmg proxy env) ?? $GITHUB_ENV or something like that. Works in a generic way across any environment.
For shell, I would just do:
export $(pmg proxy env | xargs)
| python -m venv venv && source venv/bin/activate | ||
| pip install requests==2.32.4 | ||
| python -c "import requests; print('pip ok:', requests.__version__)" | ||
| deactivate && rm -rf venv |
There was a problem hiding this comment.
Add test for the case of malicious package installation via. python3 -m pip install x
|
|
||
| - name: Start persistent proxy | ||
| run: | | ||
| pmg proxy start & |
There was a problem hiding this comment.
Will the proxy server work if I run it as root, something like sudo proxy start --daemon --state /root/pmg-proxy.state
|
|
||
| - name: Stop proxy | ||
| if: always() | ||
| run: pmg proxy stop |
There was a problem hiding this comment.
By default pmg proxy stop should just stop the proxy and not fail due to policy violations. I feel that is non-intuitive. Failing on policy violations to block CI should be something like:
pmg proxy stop --fail-on-violation that clearly states that the stop command fails if any violation (policy or malicious package) detected.
There was a problem hiding this comment.
A good UX will be for pmg proxy stop --violations to print all the violations and pmg proxy stop --violations --json /tmp/a.json to write the violations in a JSON file so that the GitHub Action can read the JSON and add it as a formatted comment in GitHub PR.
But it can be a separate enhancements (UX).
|
Superseded by #351 — the persistent proxy server MVP. #351 is a clean branch off |



Summary
pmg proxycommand group withstart,stop,env, andstatussubcommandsHow it works
GHA example
Changes
internal/proxystate— state file (pid/addr/ca-cert-path) with liveness checkinternal/flows/cert.go— extracted sharedSetupCACertificate(removes duplication fromproxy_flow.go)cmd/proxy/{start,stop,env,status}.go— command implementations.github/workflows/persistent-proxy-e2e.yml— E2E test for persistent proxy mode (trigger viaworkflow_dispatchon this branch)