Skip to content

[WSLC] Reapply "[WSLC] Add cooperative HTTP/HTTPS proxy support" - #713

Merged
Soham Das (SohamDas2021) merged 2 commits into
mainfrom
user/sodas/reapply-wslc-enable-http-proxy
Jul 30, 2026
Merged

[WSLC] Reapply "[WSLC] Add cooperative HTTP/HTTPS proxy support"#713
Soham Das (SohamDas2021) merged 2 commits into
mainfrom
user/sodas/reapply-wslc-enable-http-proxy

Conversation

@SohamDas2021

@SohamDas2021 Soham Das (SohamDas2021) commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

This reverts commit ea8f405, restoring the WSLC cooperative HTTP/HTTPS proxy support originally added in #652.

📖 Description

🔗 References

🔍 Validation

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task

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 GitHub
Actions build; it runs on merge to main, and Microsoft reviewers with write access can trigger it
on a PR with /azp run. See docs/pull-requests.md.

If the dependency-feed-check check fails on a new dependency, the crate must be added to
the feed before the PR can pass. See docs/pull-requests.md
for the steps.

Microsoft Reviewers: Open in CodeFlow

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
@SohamDas2021
Soham Das (SohamDas2021) requested a review from a team as a code owner July 30, 2026 18:40
Copilot AI review requested due to automatic review settings July 30, 2026 18:40
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 https module does not honor these variables by default; it requires NODE_USE_ENV_PROXY=1/--use-env-proxy on 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 thread src/core/wxc_common/src/config_parser.rs
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 thread sdk/node/src/types.ts
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). */
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
Copilot AI review requested due to automatic review settings July 30, 2026 19:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_proxy runs before the containment checks, so it newly rejects non-HTTP URL schemes for ProcessContainer, Bubblewrap, and Seatbelt too. That contradicts the new types.ts documentation, 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, although PROXY_SET_KEYS injects 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.

@SohamDas2021
Soham Das (SohamDas2021) merged commit 839ace4 into main Jul 30, 2026
23 checks passed
@SohamDas2021
Soham Das (SohamDas2021) deleted the user/sodas/reapply-wslc-enable-http-proxy branch July 30, 2026 19:26
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.

3 participants