Skip to content

[WSLC] Add cooperative HTTP/HTTPS proxy support - #652

Open
SohamDas2021 wants to merge 6 commits into
mainfrom
user/sodas/wslc-enable-http-proxy
Open

[WSLC] Add cooperative HTTP/HTTPS proxy support#652
SohamDas2021 wants to merge 6 commits into
mainfrom
user/sodas/wslc-enable-http-proxy

Conversation

@SohamDas2021

@SohamDas2021 SohamDas2021 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

📖 Description

WSLc containers run in their own network namespace (a separate WSL system VM) and the WSLc kernel has no in-kernel iptables, so per-host network enforcement is not possible. Mirror the Bubblewrap backend's cooperative model: translate network.proxy into HTTP(S)_PROXY env vars that cooperating clients (curl, wget, requests, ...) honor.

🔗 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

Copilot AI review requested due to automatic review settings July 15, 2026 22:48
@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

Adds WSLC “cooperative” HTTP/HTTPS proxy support by translating network.proxy into standard proxy environment variables (with hygiene scrubbing), aligning WSLC behavior with the existing Bubblewrap cooperative proxy model and documenting/testing it end-to-end.

Changes:

  • Added shared wxc_common::proxy_env helpers for scrubbing/setting proxy env vars and refactored Bubblewrap to use them.
  • Extended config parsing to allow network.proxy for wslc and added WSLC-specific validation (url-form only).
  • Added WSLC proxy functional test config + scripts and documented WSLC proxy behavior/caveats.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/scripts/run_wslc_proxy_test.ps1 New WSLC proxy functional test runner script
tests/scripts/run_wslc_all_tests.ps1 Adds WSLC proxy config to the all-tests suite
tests/configs/wslc_network_proxy.json New WSLC proxy test config exercising env injection + scrubbing
src/core/wxc_common/src/proxy_env.rs New shared proxy env scrubbing/injection helpers + unit tests
src/core/wxc_common/src/lib.rs Exposes the new proxy_env module
src/core/wxc_common/src/config_parser.rs Allows WSLC proxy + validates WSLC proxy must be { url } form
src/backends/wslc/common/src/wsl_container_runner.rs Injects cooperative proxy env vars into WSLC process settings
src/backends/bubblewrap/common/src/bwrap_command.rs Refactors Bubblewrap proxy env handling to shared helpers
sdk/node/src/types.ts Updates SDK docs/comments to mention WSLC proxy constraints
docs/wsl/wsl-container-getting-started.md Documents WSLC cooperative proxy model and limitations
docs/schema.md Notes WSLC proxy support and url-only constraint in schema docs

Comment thread src/core/wxc_common/src/config_parser.rs Outdated
Comment thread src/backends/wslc/common/src/wsl_container_runner.rs
Comment thread tests/scripts/run_wslc_proxy_test.ps1 Outdated
$WxcExec = $Candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
}
if (-not $WxcExec -or -not (Test-Path $WxcExec)) {
Write-Host "ERROR: wxc-exec.exe not found. Build with: cargo build --features wslc --release --target $Target" -ForegroundColor Red
@SohamDas2021
SohamDas2021 marked this pull request as ready for review July 20, 2026 18:20
@SohamDas2021
SohamDas2021 requested a review from a team as a code owner July 20, 2026 18:20
// MXC-run host-loopback proxy is unreachable. Accept only the
// caller-supplied `url` form (which carries `original_url`); reject
// the `localhost` / `builtinTestServer` forms.
if containment == ContainmentBackend::Wslc && proxy_config.is_enabled() {

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.

The WSLc url-form guard only checks original_url.is_some(), so a loopback URL like {"url":"http://127.0.0.1:8080"} or http://[::1]:8080 is accepted here. That is the same host-loopback target the localhost form is rejected for, since a WSLc container runs in its own network namespace and cannot reach the host loopback. As written this contradicts its own rationale: the localhost form is blocked but the identical address slips through via url. Because WSLc requires defaultPolicy=allow, the sandbox then gets connection-refused to a proxy that can never work while traffic is otherwise unrestricted. Please also reject loopback and unspecified hosts (127.0.0.0/8, ::1, 0.0.0.0, ::) for the WSLc url form, and add a test covering http://127.0.0.1:8080.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A WSLC container runs in its own network namespace (separate VM), so the 127.0.0.1 in wslc_network_proxy.json is the container's own loopback, not the host's- the host loopback isn't reachable from a WSLC container at all. Rejecting it would break that documented, tested pattern

@huzaifa-d

Copy link
Copy Markdown
Contributor

On config_parser.rs around line 400 (the shared network.proxy url parsing, not part of this diff): the url form validates host and port but not the scheme, so ftp://proxy:21 or socks5://proxy:1080 are accepted and then injected as HTTP_PROXY/HTTPS_PROXY values. Some HTTP clients silently ignore a non-HTTP proxy scheme, which fails open under the WSLc defaultPolicy=allow requirement. Consider restricting accepted schemes to http and https (or explicitly documenting socks support if intended). Shared across backends, so likely a follow-up rather than blocking this PR.

Copilot AI review requested due to automatic review settings July 27, 2026 21:34

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 4 comments.

Comments suppressed due to low confidence (1)

docs/wsl/wsl-container-getting-started.md:247

  • Node's built-in http/https clients do not honor these variables by default. Current supported releases require explicit NODE_USE_ENV_PROXY=1 or --use-env-proxy opt-in, while older supported Node versions need a proxy agent. Listing Node here without that qualification can cause traffic to bypass the proxy unexpectedly.
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/proxy_env.rs Outdated
Comment on lines +39 to +41
/// Only the HTTP/HTTPS keys (upper- and lower-case) are set. `NO_PROXY` is
/// deliberately omitted (see module docs).
pub const PROXY_SET_KEYS: &[&str] = &["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"];
$pass = $false
$reason = "runner did not inject/scrub HTTP_PROXY (expected http://127.0.0.1:8888)"
}
if ($pass -and ($output -match "attacker\.invalid")) {
Comment on lines +242 to +245
Any caller-supplied values for these keys — including `NO_PROXY` /
`no_proxy` — are **stripped** first, so a workload cannot override or
disable the configured proxy. The runner deliberately does **not** set
`NO_PROXY`.
Comment thread sdk/node/src/types.ts Outdated
Comment on lines +207 to +209
* WSLC accepts only the `{ url }` form (its containers run in their own network
* namespace, so the `localhost` / `builtinTestServer` loopback forms are
* unreachable and rejected); enforcement is cooperative (no in-kernel iptables). */
…e-http-proxy

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f3ae1af2-7b79-4340-a5ce-a5402e7ede3d

# Conflicts:
#	sdk/node/src/types.ts
#	src/backends/bubblewrap/common/src/bwrap_command.rs
#	src/core/wxc_common/src/config_parser.rs
Copilot AI review requested due to automatic review settings July 27, 2026 21:55

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 1 comment.


Write-Host "`n--- Network Tests ---" -ForegroundColor Cyan
$null = $results.Add((Run-WslcTest "wslc_network_isolated.json"))
$null = $results.Add((Run-WslcTest "wslc_network_proxy.json" -OutputContains "WSLC_PROXY_FUNCTIONAL_OK"))
@SohamDas2021
SohamDas2021 requested a review from huzaifa-d July 27, 2026 22:42
@SohamDas2021

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

…as/wslc-enable-http-proxy

# Conflicts:
#	src/backends/wslc/common/src/wsl_container_runner.rs
Copilot AI review requested due to automatic review settings July 28, 2026 05:39

Copilot AI commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved. The only conflict was in wsl_container_runner.rs where both our proxy env injection code and main's WSLC FFI rebinding (PR #669) touched the WslcSetProcessSettingsEnvVariables call. The resolution keeps our effective_env/lifetime-management approach while adopting main's new method-call syntax (sdk.WslcSetProcessSettingsEnvVariables(...)).

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:427

  • This validation changes every backend, not just WSLC. Before this hunk, Bubblewrap and Seatbelt accepted URLs such as socks5://proxy:1080 and passed the preserved URL to clients that support SOCKS proxy schemes; those existing configs will now fail parsing even though the fail-open rationale here is WSLC-specific. Please scope the scheme restriction to the WSLC branch (and make this test use containment: "wslc"), or explicitly treat and document this as a breaking cross-backend API change.
        // Only http/https are meaningful for the HTTP(S)_PROXY env vars we
        // inject. A non-HTTP scheme (ftp://, socks5://, …) is silently ignored
        // by many clients, which fails open under WSLc's defaultPolicy=allow.
        let scheme = parsed.scheme();
        if scheme != "http" && scheme != "https" {

src/core/wxc_common/src/proxy_env.rs:37

  • FTP_PROXY/ftp_proxy are missing from the managed set. A cooperating client such as curl gives a scheme-specific FTP proxy precedence over ALL_PROXY, so caller-supplied values can survive an active proxy policy. This also conflicts with the repository's proxy hygiene requirement in docs/linux-wsl-roadmap-june-2026.md:104,379 and docs/sandbox-policy/v2/networking.md:217, which explicitly lists both variants. Add them to the scrubbed keys (not the set keys).
    "NO_PROXY",
    "no_proxy",

sdk/node/src/types.ts:205

  • The primary SandboxPolicy.network.proxy documentation in this same file (types.ts:352-360) still says the proxy is supported only on ProcessContainer, Bubblewrap, and Seatbelt. Since SandboxPolicy is what spawnSandbox consumes, WSLC users will still see contradictory API documentation despite this update to the lower-level ContainerConfig type. Please update that public policy comment too, including WSLC's URL-only/allowOutbound combination rules.
  /** Proxy configuration (supported on Windows ProcessContainer, Linux Bubblewrap,
   *  macOS Seatbelt, and WSLC). On Bubblewrap/Seatbelt/WSLC it is a cooperative
   *  env-var proxy (HTTP_PROXY/HTTPS_PROXY): well-behaved HTTP clients honor it,

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.

5 participants