Skip to content

[WSLC] Honor state-aware portMappings and reject redundant one-shot host lists (Closes #824) - #862

Open
Soham Das (SohamDas2021) wants to merge 1 commit into
mainfrom
user/sodas/wslc-824-network-parity
Open

[WSLC] Honor state-aware portMappings and reject redundant one-shot host lists (Closes #824)#862
Soham Das (SohamDas2021) wants to merge 1 commit into
mainfrom
user/sodas/wslc-824-network-parity

Conversation

@SohamDas2021

@SohamDas2021 Soham Das (SohamDas2021) commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

📖 Description


Summary

Brings the WSLc state-aware network-policy surface into parity with the one-shot surface (#824), closing two gaps where the two paths silently diverged, plus supporting doc/test fixes.

Gap 1 — one-shot dropped redundant host lists. A host list that was redundant with the default (blockedHosts under defaultPolicy: "block", allowedHosts under "allow") previously slipped past needs_host_filtering() and was silently ignored — a fail-open footgun, since WSLc cannot enforce per-host filtering (no CAP_NET_ADMIN, no VM-level hook). The parser now rejects any non-empty allowedHosts/blockedHosts up front (has_host_lists()). Bare defaultPolicy with no host lists (full cutoff / full NAT) stays supported.

Gap 2 — state-aware dropped provision-time portMappings. experimental.wslc.provision.portMappings was accepted but never wired into the container's WSL2 NAT. Added the field to the provision wire/domain model, mapped it through build_provision_config, and bumped the daemon PROTOCOL_VERSION (2 → 3) so the host->container forward is actually installed. Now verified by a functional round-trip.

Error-code parity fix

Widening Gap 1 initially made state-aware requests with host lists fail at parse time as malformed_request. State-aware requests now skip the parser-level host-list rejection (via a state_aware flag threaded into convert_wire_config) and fall through to the backend's reject_host_filtering policy gate, which reports the well-formed-but-unsupported policy as policy_validation — matching every other post-parse policy rejection. One-shot keeps the parse-time rejection (it has no backend gate). The neighbouring allowLocalNetwork rejection deliberately stays firing on both paths, since the provision policy gate does not cover it (gating it would fail-open).

Tests & docs

  • New fixture tests/configs/wslc_state_aware_provision_ports.json.
  • run_wslc_state_aware_tests.ps1 C2 rewritten from a provision/start/exec smoke into a real port round-trip: a detached in-container listener on port 80, connected through the mapped Windows host port 18080 with a payload assertion — genuinely regresses [WSLC] One-shot vs state-aware network-policy parity: fail-open redundant host lists and dropped portMappings #824.
  • docs/wsl/wsl-container-getting-started.md updated: all non-empty host lists (incl. redundant combos) are rejected, with the current error message and the one-shot (parse) vs state-aware (policy_validation) distinction.

Validation

  • cargo fmt / clippy -p wxc_common -D warnings clean; cargo test -p wxc_common (594) and cargo test --workspace green.
  • WSLc state-aware E2E harness on a live WSL2 host: 63/63 passed (incl. the new port round-trip and the corrected policy_validation rejection).

Closes #824

📋 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 balanced review requested due to automatic review settings August 14, 2026 03:23
@azure-pipelines

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

@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

Aligns WSLc one-shot and state-aware networking behavior by rejecting unsupported host lists and enabling provision-time port forwarding.

Changes:

  • Rejects all non-empty WSLc host lists.
  • Threads state-aware port mappings through the daemon.
  • Adds schema, SDK, documentation, and E2E coverage.

Reviewed changes

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

Show a summary per file
File Description
tests/scripts/run_wslc_state_aware_tests.ps1 Adds port-forward E2E coverage.
tests/configs/wslc_state_aware_provision_ports.json Adds port-mapping fixture.
src/core/wxc_common/src/wire.rs Adds provision port mappings.
src/core/wxc_common/src/models.rs Adds host-list detection.
src/core/wxc_common/src/config_parser.rs Enforces WSLc host-list policy.
src/backends/wslc/daemon/tests/daemon_ipc.rs Updates daemon IPC test.
src/backends/wslc/daemon/src/session_manager.rs Applies daemon port mappings.
src/backends/wslc/common/src/wsl_container_runner.rs Rejects all host lists.
src/backends/wslc/common/src/state_aware.rs Maps and validates provision ports.
src/backends/wslc/common/src/daemon_protocol.rs Extends and versions daemon protocol.
src/backends/wslc/common/src/container_steps.rs Configures mapped ports.
sdk/node/tests/unit/wire-conformance-state-aware.test.ts Checks SDK wire conformity.
sdk/node/src/state-aware-types.ts Exposes state-aware port mappings.
sdk/node/src/generated/wire.ts Regenerates wire types.
schemas/dev/mxc-config.schema.0.8.0-dev.json Regenerates development schema.
docs/wsl/wslc-state-aware.md Documents port forwarding.
docs/wsl/wsl-container-getting-started.md Documents host-list rejection.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +190 to +197
/**
* Host↔container port mappings applied at provision and frozen for the life
* of the sandbox. Per-container (not per-session), so — unlike the one-shot
* sizing knobs — they are honored here, matching the one-shot surface. Only
* TCP is supported (`protocol` defaults to `"tcp"`); `"udp"` is rejected.
* Nested under `experimental.wslc.provision.portMappings` on the wire.
*/
portMappings?: PortMapping[];
Comment on lines +765 to +769
if ($portListenerOk) {
Run-StateAwareTest "C2: port forward round-trip (windows 18080 -> container 80)" {
$payload = Get-TcpResponse -HostName '127.0.0.1' -Port 18080
Assert-True ($payload -eq 'MXC_PORTMAP_OK') `
"host port 18080 forwards to the container listener (got '$payload')"
Comment on lines +365 to +369
if m.windows_port == 0 {
return Err(MxcError::policy_validation(format!(
"experimental.wslc.provision.portMappings[{idx}]: 'windowsPort' must be > 0"
)));
}
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.

[WSLC] One-shot vs state-aware network-policy parity: fail-open redundant host lists and dropped portMappings

2 participants