[Bubblewrap] Make Bubblewrap the default Linux backend#368
Conversation
There was a problem hiding this comment.
Pull request overview
Updates MXC’s Linux containment resolution so the abstract “process” intent (and omitted containment) routes to Bubblewrap by default, while keeping explicit containment: "lxc" working as an opt-in path. This fits into the codebase’s “abstract intent → per-OS concrete backend” design in wxc_common::config_parser.
Changes:
- Change Rust config parsing so omitted
containmentandcontainment: "process"resolve toContainmentBackend::Bubblewrapon Linux. - Add/adjust SDK unit + integration tests to exercise the new default and to keep explicit LXC coverage via an explicit
containment: "lxc"config. - Add CLI-level test configs + scripts to validate default Linux process behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
test_scripts/run_linux_process_default_test.sh |
New script to run configs that exercise Linux default/abstract process containment resolution. |
test_scripts/run_bwrap_all_tests.sh |
Includes the new default-process test script and line-ending checks for it. |
test_configs/linux_process_default.json |
New config to validate “containment omitted” Linux default behavior. |
test_configs/linux_process_abstract.json |
New config to validate containment: "process" behavior on Linux. |
src/wxc_common/src/config_parser.rs |
Core behavior change: Linux default + "process" resolve to Bubblewrap; adds parser tests/regressions. |
src/lxc/src/main.rs |
Updates dispatch comment to reflect Bubblewrap being the Linux default for abstract intents. |
sdk/tests/unit/sandbox.test.ts |
Adds unit coverage for Bubblewrap mapping and explicit LXC opt-in behavior. |
sdk/tests/integration/test-helpers.ts |
Adds a helper to run spawnSandboxFromConfig as a Promise for tests. |
sdk/tests/integration/linux-process-container.test.ts |
Routes these tests through explicit containment: "lxc" to keep exercising LXC. |
sdk/tests/integration/linux-bubblewrap.test.ts |
New integration coverage for Bubblewrap as the silent default and for explicit selection. |
sdk/src/sandbox.ts |
Adds explicit containment === 'lxc' handling; updates Linux 'process' diagnostic logging. |
Six proxy tests omitted containment and relied on the previous unconditional ProcessContainer default to satisfy the proxy guard (proxy is only valid with processcontainer). After this PR the default resolves to Seatbelt on macOS, causing those six tests to fail in the arm64 MAC CI job. Make each test explicit by setting containment: "processcontainer" in the JSON — they are testing proxy parsing behavior, not the OS-default resolution. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/mxc/sessions/81dc5e19-9e89-4a1a-a005-6633f4ffbfe8 Co-authored-by: huzaifa-d <16077119+huzaifa-d@users.noreply.github.com>
PR 368 introduces SDK integration tests that exercise the Bubblewrap backend (the new Linux default for `containment: "process"` / omitted). Those tests skip unless `bwrap` is installed on the runner; the Linux integration job previously only installed `lxc`, so the new bwrap tests failed under sudo. Add `bubblewrap` to the apt-get install line alongside `lxc lxc-utils dnsmasq-base iptables` so both backends are present and both test suites can run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| // Async spawn from a pre-built ContainerConfig (no per-call containment arg on | ||
| // spawnSandboxAsync, so tests that need a specific backend build the config | ||
| // directly and run it through this helper). | ||
| export function spawnFromConfigAsync( |
There was a problem hiding this comment.
Suggestion - Don't ignore stderr. Consider a timeout too. And have a on error handler.
There was a problem hiding this comment.
This helper emulates the SDK's spawnSandboxAsync; the SDK doesn't expose an async wrapper around spawnSandboxFromConfig. Goal is parity with spawnSandboxAsync.
stderr- not ignored. wxc-exec runs under node-pty (single PTY), so stdout/stderr are merged at the OS level. node-pty only exposes one onData. The SDK does the same thing and comments it on sandbox.ts:666. I'll mirror that comment here.
timeout- spawnSandboxAsync doesn't have one either. node --test enforces per-test timeouts, and the config's process.timeout is enforced by the native runner.
onError- node-pty's IPty has no onError event. Sync spawn failures hit the existing try/catch; post-spawn failures surface as a non-zero exitCode via onExit
| * Containment values (abstract intent or concrete backend) that require | ||
| * the `--experimental` flag. | ||
| */ | ||
| export const ExperimentalBackends: readonly (ContainmentType | ContainmentBackend)[] = ['microvm', 'wslc', 'seatbelt', 'bubblewrap']; |
There was a problem hiding this comment.
Now that bubblewrap is default, should it still need experimental? If yes, do the default process paths check/throw if not experimental?
There was a problem hiding this comment.
Once we promote bubblewrap to stable, this will be cleaned up. Currently default process paths do not check for experimental. This are the scenarios:
Linux containment resolution matrix
containment |
SDK gate | Native dispatcher resolves to |
|---|---|---|
| (omitted) | none | Bubblewrap |
"process" |
none | Bubblewrap |
"lxc" |
none | LXC |
"bubblewrap" |
requires experimental: true (SDK only) |
Bubblewrap |
"processcontainer" |
none | LXC (catch-all fallback) |
…411) * Fix: exempt abstract 'process' on macOS from allowOutbound precheck On macOS, the abstract containment 'process' resolves to the seatbelt backend, which supports per-host network filtering natively via sandbox-exec profiles. The SDK precheck incorrectly required allowOutbound=true for allowedHosts/blockedHosts when using the default 'process' containment on macOS, despite the explicit 'seatbelt' backend being correctly exempted. Add 'darwin' platform check to resolvesToHostFilteringBackend alongside the existing 'linux' check (which maps to bubblewrap). Add unit tests mirroring the Linux coverage from PR #368. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix blockedHosts test: remove allowOutbound to actually test the precheck waiver --------- Co-authored-by: Richie Gomez <richiegomez@Richies-Mac-mini.local> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📖 Description
Makes Bubblewrap the default Linux process-sandbox backend. Callers that omit
containment, or set the abstractcontainment: "process", now get Bubblewrap instead of LXC. Explicitcontainment: "lxc"and explicitcontainment: "bubblewrap"continue to work as before.Linux containment resolution matrix
containment"process""lxc""bubblewrap"experimental: true(SDK only)"processcontainer"Note: the experimental gate on explicit
"bubblewrap"is enforced at the SDK layer only (helper.tsExperimentalBackends`); the native binary does not re-check it. This is the same behavior as the original Bubblewrap PR (#314) and is unchanged here.🔗 References
🔍 Validation
✅ Checklist
📋 Issue Type
Microsoft Reviewers: Open in CodeFlow