Skip to content

[Bubblewrap/LXC/WSLC] Update roadmap doc#675

Open
SohamDas2021 wants to merge 2 commits into
mainfrom
user/sodas/update-roadmap-doc
Open

[Bubblewrap/LXC/WSLC] Update roadmap doc#675
SohamDas2021 wants to merge 2 commits into
mainfrom
user/sodas/update-roadmap-doc

Conversation

@SohamDas2021

@SohamDas2021 SohamDas2021 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

📖 Description

Update roadmap doc with the state of the work-items. Align LXC/Bwrap N2 inbound control with GA networking spec.

🔗 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 23, 2026 21:38
@SohamDas2021
SohamDas2021 requested a review from a team as a code owner July 23, 2026 21:38
@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

Updates the Linux/WSL roadmap to reflect backend progress and align inbound networking plans with the GA specification.

Changes:

  • Updates filesystem-policy work-item statuses.
  • Revises LXC/Bubblewrap inbound-control plans.
  • Clarifies WSLC limitations and dependencies.
Comments suppressed due to low confidence (3)

docs/linux-wsl-roadmap-june-2026.md:164

  • This repeats an ingress rule set that is broader than the GA contract: NEW ACCEPT in the private namespace permits direct connections over the veth, not just host-loopback traffic, while -i lo is only sandbox-internal loopback. The N1 routed-proxy design needs to define a host-side listener bound to 127.0.0.1/::1 and an INPUT rule scoped to that forwarding path rather than accepting every new connection.
| 14 | **(N2) Inbound control (`hostLoopback`)** | 🟡 Actionable | Already in place: `--unshare-net` inherently blocks inbound (no route). New work (proxy mode): GA requires ingress enforced via an iptables **INPUT** chain in the sandbox's **own network namespace** (`docs/sandbox-policy/v2/networking.md` L148/L212/L289/L295), scoped per-sandbox (D6). This **depends on N1** moving proxy mode off the shared host netns onto `--unshare-net` + a routed proxy (slirp4netns/veth, elevation required). Once Bwrap has a private netns, ingress runs there via the shared `NetworkIptablesManager` — `-i lo` ACCEPT, `ESTABLISHED,RELATED` ACCEPT, `NEW` ACCEPT/DROP keyed on `ingress.hostLoopback`/`allowLocalNetwork`, terminal DROP — same as LXC. A host-side INPUT chain on the shared netns is **not** the GA target: it can't be attributed to a single sandbox. | M |

docs/linux-wsl-roadmap-june-2026.md:232

  • This describes the old behavior as current, but WSLC already calls validate_denied_path_overlap() before loading the SDK (wsl_container_runner.rs:892-905), and a wiring test verifies rejection before container startup. Update both this row and its example so the roadmap does not list completed mitigation as actionable.
| 5 | **`deniedPaths` overlap validation** | 🟡 Actionable | Today a `deniedPaths` entry that is a child of a mounted (`readwritePaths`/`readonlyPaths`) path is silently ignored, leaving it accessible through the parent mount. Planned: reject such configs at parse time (since the WSLC SDK cannot enforce the deny). Non-overlapping denied paths are already implicitly enforced (unmounted = invisible). This is a workaround; *masking* a denied subtree under a mounted parent needs an SDK exclusion primitive (see [WSLC SDK dep #4](#wslc-sdk-dependencies)). | S |

docs/linux-wsl-roadmap-june-2026.md:471

  • This dependency summary reintroduces the same obsolete claim as filesystem item #5. The current runner already rejects nested denied paths before SDK load, so saying MXC silently ignores them and only plans to reject them makes the roadmap internally inconsistent and understates the current fail-closed behavior.
| 4 | **Deny-mount / path-exclusion primitive** | Filesystem #5 (`deniedPaths` enforcement) | LXC and Bubblewrap mask a `deniedPaths` entry that sits under a mounted parent by overlaying it (`/dev/null` or `tmpfs`). The WSLC SDK exposes only a flat volume-mount surface with no overlay/exclusion primitive, so a denied subtree under a mounted parent cannot be masked. Today MXC silently ignores such a denied path, leaving it accessible through the parent mount; the planned near-term mitigation is to reject these configs at parse time (Filesystem #5), but real enforcement needs an SDK exclusion primitive. (Note: this is the *basic subtree-deny* gap — spec-exact D5 "visible + ACCESS_DENIED" remains non-actionable on every Linux backend regardless, see Filesystem #12.) |

Comment on lines +46 to 48
| 4 | **(D4) Most-specific-path-wins** | 🟡 Actionable | No path-specificity engine — mount ordering determines behavior, not longest-prefix match. The shared path-tree resolver now exists in `wxc_common` (`filesystem_resolve.rs`, [PR #608](https://github.com/microsoft/mxc/pull/608)); LXC needs to consume it. | M |

> **Example (D4).** Policy: `RW /workspace`, `RO /workspace/.git`, `D /workspace/.env`. The spec says writes to `.git/config` are denied (inner RO wins) and reads of `.env` are denied (inner D wins). Today LXC applies three independent `lxc.mount.entry` lines — the result depends on which mount comes last, not specificity.
Comment on lines +58 to 60
| 6 | **(D3) Delegation check** | ✅ Addressed | Policy grants are bounded by the invoking user's access: shared `check_delegation()` in `wxc_common` (`filesystem_access.rs`) verifies the user can read/write each listed path before accepting the config, wired into all three runners. Done in [PR #598](https://github.com/microsoft/mxc/pull/598). | M |

> **Example (D3).** User "alice" has no read access to `/root/secrets`. Policy: `{ readonlyPaths: ["/root/secrets"] }`. Today: accepted silently. If the container runs as root, the mount succeeds and the agent reads the secrets. Spec: validator rejects at load time.
|---|---|---|---|---|
| 13 | **(N1) Default-deny outbound** | 🟡 Actionable | Already in place: iptables FORWARD hook with default DROP when firewall mode + veth detected. New work: ensure hook is always applied; fail-fast if veth not found rather than silently skipping. | M |
| 14 | **(N2) Inbound control (`hostLoopback`)** | 🟡 Actionable | `allowLocalNetwork` is parsed but silently ignored. New work: add iptables FORWARD rules on the container veth — DROP new inbound by default; ACCEPT from host loopback when `ingress.hostLoopback: "allow"`. | M |
| 14 | **(N2) Inbound control (`hostLoopback`)** | 🟡 Actionable | `allowLocalNetwork` is parsed but silently ignored. New work: add an ingress chain in the container's **network namespace** (via `nsenter -t <init-pid> -n iptables`, hooked with `-I INPUT`) — `-i lo` ACCEPT, `ESTABLISHED,RELATED` ACCEPT, `NEW` ACCEPT/DROP keyed on `ingress.hostLoopback`/`allowLocalNetwork`, terminal DROP. This matches the GA spec (`docs/sandbox-policy/v2/networking.md`), which enforces ingress on all Linux backends via the container-netns **INPUT** chain. Supersedes the earlier host-side FORWARD-on-veth approach, which was dead for host→container-direct packets: the destination is the container's own IP, so those packets traverse container **INPUT**, not host FORWARD. | M |
> ```
>
> This forwards host `127.0.0.1:3000` → container `:3000`. TCP only — UDP is rejected at parse time because the shipped runtime returns `E_NOTIMPL`.
> This forwards host `127.0.0.1:3000` → container `:3000`. TCP only — UDP is rejected at parse time because the shipped runtime (Microsoft.WSL.Containers 2.8.1) returns `E_NOTIMPL`.
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.

2 participants