[WSLC] Reapply "[WSLC] Add cooperative HTTP/HTTPS proxy support" - #713
Merged
Soham Das (SohamDas2021) merged 2 commits intoJul 30, 2026
Merged
Conversation
This reverts commit ea8f405, restoring the WSLC cooperative HTTP/HTTPS proxy support originally added in #652. Resolved a trivial conflict in config_parser.rs (proxy-supported-backends error message) by keeping the 'wslc' variant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cce70ecd-1449-465e-8a87-a9880a0a10c0
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
Restores cooperative HTTP/HTTPS proxy support for WSLC while sharing proxy environment handling with Bubblewrap.
Changes:
- Adds WSLC proxy validation and environment injection.
- Introduces shared proxy-variable sanitization and redaction.
- Adds functional tests and documentation.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
tests/scripts/run_wslc_proxy_test.ps1 |
Adds WSLC proxy E2E test. |
tests/scripts/run_wslc_all_tests.ps1 |
Runs the proxy fixture. |
tests/configs/wslc_network_proxy.json |
Defines proxy test configuration. |
src/core/wxc_common/src/proxy_env.rs |
Adds shared proxy environment helpers. |
src/core/wxc_common/src/lib.rs |
Exports proxy helpers. |
src/core/wxc_common/src/config_parser.rs |
Validates WSLC proxy configurations. |
src/backends/wslc/common/src/wsl_container_runner.rs |
Injects proxy environment variables. |
src/backends/bubblewrap/common/src/bwrap_command.rs |
Reuses shared proxy helpers. |
sdk/node/src/types.ts |
Documents SDK proxy constraints. |
docs/wsl/wsl-container-getting-started.md |
Documents WSLC proxy usage. |
docs/schema.md |
Notes WSLC URL-form support. |
Comments suppressed due to low confidence (1)
docs/wsl/wsl-container-getting-started.md:251
- Node's built-in
httpsmodule does not honor these variables by default; it requiresNODE_USE_ENV_PROXY=1/--use-env-proxyon supported Node versions (or a custom proxy agent). Listing it alongside clients that work without extra opt-in will lead users to expect traffic to be proxied when it is not.
2. Cooperative tools (curl, wget, Python `requests`, Node `https`, etc.) honor
the env vars and their traffic flows through the proxy.
Comment on lines
+106
to
+110
| # The cooperating client must have routed through the marker proxy. | ||
| if ($pass -and ($output -notmatch "WSLC_PROXY_FUNCTIONAL_OK")) { | ||
| $pass = $false | ||
| $reason = "client did not route through the proxy (marker 'PROXY_HIT' not observed)" | ||
| } |
| | `"allowOutbound": true` | Bridged networking (full access) | | ||
| | `"allowOutbound": false` | No networking (isolated) | | ||
|
|
||
| ### Network proxy (cooperative, unprivileged) |
Comment on lines
+232
to
+236
| WSLC supports a **cooperative HTTP/HTTPS proxy**: setting `network.proxy` | ||
| routes a container's egress through a proxy you provide. WSLC's kernel has | ||
| **no in-kernel `iptables`**, so — exactly like the Bubblewrap backend — there | ||
| is no netfilter drop-floor; enforcement is *cooperative*, applied by handing | ||
| the workload proxy environment variables that well-behaved clients honor. |
Comment on lines
+283
to
+285
| **not** contained. WSLC cannot provide a hard network floor because its | ||
| kernel lacks `iptables`. For strict network isolation, use | ||
| `"allowOutbound": false` (no networking) instead. |
Comment on lines
+7
to
+9
| //! When a backend cannot install a netfilter drop-floor (WSLc has no | ||
| //! iptables in its kernel; Bubblewrap deliberately skips iptables while a | ||
| //! proxy is active), per-host network policy is enforced *cooperatively*: |
Comment on lines
+6
to
+8
| # WSLC has no in-kernel iptables, so per-host network policy is enforced | ||
| # *cooperatively*: the runner translates `network.proxy` into HTTP(S)_PROXY | ||
| # env vars and cooperating clients (curl, wget, ...) route through the proxy. |
Comment on lines
+978
to
+980
| // Route egress through the cooperative proxy: WSLc has no in-kernel | ||
| // iptables, so per-host policy is enforced at the proxy layer by | ||
| // injecting HTTP(S)_PROXY (and scrubbing caller-supplied proxy vars). |
Comment on lines
+220
to
+230
| * WSLC imposes additional parse-time constraints (a violating config is | ||
| * rejected before it runs): | ||
| * - Only the `{ url }` form is accepted — its containers run in their own | ||
| * network namespace, so the `localhost` / `builtinTestServer` loopback | ||
| * forms are unreachable and rejected. | ||
| * - The `url` scheme must be `http` or `https`. | ||
| * - `defaultPolicy` must be `"allow"` and both `allowedHosts` and | ||
| * `blockedHosts` must be empty/unset — WSLC has no in-kernel iptables, so | ||
| * it cannot enforce host lists, and the container needs outbound | ||
| * networking to reach the proxy at all. | ||
| * Enforcement is cooperative (no in-kernel iptables). */ |
Huzaifa Danish (huzaifa-d)
approved these changes
Jul 30, 2026
The `network.proxy.url` scheme check interpolated the raw URL into the `ConfigParse` error, which reaches the diagnostic/log stream. Proxy URLs commonly embed basic-auth userinfo (`user:password@host`), so a rejected non-http(s) URL would leak the password into logs. Route it through the existing `redact_proxy_url` helper (already used on the logging path) so only `***@host` is shown. Add a regression test asserting the credential is redacted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cce70ecd-1449-465e-8a87-a9880a0a10c0
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
src/core/wxc_common/src/config_parser.rs:490
- This validation is not WSLC-specific:
convert_wire_proxyruns before the containment checks, so it newly rejects non-HTTP URL schemes for ProcessContainer, Bubblewrap, and Seatbelt too. That contradicts the newtypes.tsdocumentation, which lists the scheme restriction under “WSLC imposes additional parse-time constraints,” and changes the behavior of existing backends in a WSLC restoration PR. Either move this check into the WSLC branch or document and validate the cross-backend API change explicitly.
let scheme = parsed.scheme();
if scheme != "http" && scheme != "https" {
// Redact any embedded userinfo (`user:password@`) before it reaches
// the diagnostic/log stream — a proxy URL commonly carries basic-auth
// credentials, and the scheme alone diagnoses the failure.
let redacted = crate::proxy_env::redact_proxy_url(&url_str);
return Err(WxcError::ConfigParse(format!(
"network.proxy.url must use the 'http' or 'https' scheme (got '{scheme}'): {redacted}"
src/core/wxc_common/src/config_parser.rs:995
- This error is internally contradictory: it says the host lists are enforced by the proxy while also saying they are not forwarded to it. The external proxy cannot enforce MXC's lists unless the user configures equivalent policy there, so the message should direct users to configure host filtering on the proxy instead.
let msg = "WSLc: network.proxy requires network.defaultPolicy='allow' and no \
allowedHosts/blockedHosts. A WSLc container reaches the proxy only \
with outbound networking enabled, and host lists are enforced by the \
proxy, not forwarded to it.";
docs/wsl/wsl-container-getting-started.md:244
- The detailed behavior description omits
ALL_PROXY/all_proxy, althoughPROXY_SET_KEYSinjects both and caller-supplied values are scrubbed. This matters to consumers because enabling the feature overwrites those variables too; list all six injected keys (or say “and their lowercase variants, including ALL_PROXY”) so the documented environment contract matches the implementation.
1. When `network.proxy` is set, the runner translates it into the
`HTTP_PROXY`, `HTTPS_PROXY`, `http_proxy`, and `https_proxy` environment
variables inside the container (via `WslcSetProcessSettingsEnvVariables`).
Any caller-supplied values for these keys — including `NO_PROXY` /
`no_proxy` — are **stripped** from the *initial* process environment first.
Huzaifa Danish (huzaifa-d)
approved these changes
Jul 30, 2026
Soham Das (SohamDas2021)
deleted the
user/sodas/reapply-wslc-enable-http-proxy
branch
July 30, 2026 19:26
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.
This reverts commit ea8f405, restoring the WSLC cooperative HTTP/HTTPS proxy support originally added in #652.
📖 Description
🔗 References
🔍 Validation
✅ Checklist
Cargo.lock, thedependency-feed-checkcheck passes (see docs/pull-requests.md)📋 Issue Type
GitHub Actions runs the PR validation build automatically. The ADO pipeline
(
MXC-PR-Build) is the Azure version of the PR pipeline, kept in parity with the GitHubActions build; it runs on merge to
main, and Microsoft reviewers with write access can trigger iton a PR with
/azp run. See docs/pull-requests.md.If the
dependency-feed-checkcheck fails on a new dependency, the crate must be added tothe feed before the PR can pass. See docs/pull-requests.md
for the steps.
Microsoft Reviewers: Open in CodeFlow