Skip to content

Rewrite the Windows Sandbox one-shot path onto an authenticated protocol (Phase 1)#577

Open
MGudgin wants to merge 1 commit into
user/gudge/wsb-phase0-shared-plumbingfrom
user/gudge/wsb-phase1-one-shot
Open

Rewrite the Windows Sandbox one-shot path onto an authenticated protocol (Phase 1)#577
MGudgin wants to merge 1 commit into
user/gudge/wsb-phase0-shared-plumbingfrom
user/gudge/wsb-phase1-one-shot

Conversation

@MGudgin

@MGudgin MGudgin commented Jun 26, 2026

Copy link
Copy Markdown
Member

Note

Stacked on #576. This PR's base is user/gudge/wsb-phase0-shared-plumbing,
so the diff shows only the Phase 1 commit. It must merge after #576. Once
#576 lands on main, retarget this PR's base to main (GitHub auto-retargets
when the base branch is deleted on merge).


Summary

Phase 1 of the Windows Sandbox rewrite stack: rewrite the Windows Sandbox
one-shot backend onto a new windows_sandbox_lifecycle crate and an
authenticated host<->guest protocol, and fix the non-elevated feature-detection
false negative. The state-aware lifecycle + host daemon (Phase 2) and the SDK
(Phase 3) follow in stacked PRs.

Details

  • New windows_sandbox_lifecycle crate: the transient one-shot
    WindowsSandboxRunner (ScriptRunner) plus reusable VM lifecycle primitives
    (vm, rendezvous, bridge, ipc_exec, policy, teardown,
    control_plane host-VM-lock/ownership + Win32 os FFI).
  • One-shot now launches a fresh disposable VM per invocation with guaranteed
    teardown on every exit path (normal/panic, Ctrl-C/shutdown handler,
    next-run reconcile) -- no warm-VM reuse. The legacy
    experimental.windows_sandbox.idleTimeoutMs/daemonPipeName fields are still
    parsed but ignored, with a stderr warning
    (WXC_WSB_ACK_ONESHOT_FRESH_VM=1 silences the per-call notice).
  • Authenticated protocol: windows_sandbox_common::auth adds a per-launch
    32-byte Nonce + 1-byte ChannelRole handshake on every TCP channel (boot +
    reconnect); the guest pairs accepted sockets by declared role, not accept
    order, defeating cross-user accept-race hijack. Guest agent rewritten
    (listener/executor/job/firewall) onto the new sandbox_protocol + auth.
  • Fixes Windows Sandbox backend misreports "not enabled" when  wxc-exec runs non-elevated #560: feature detection is now by WindowsSandbox.exe presence
    instead of an elevated dism /get-featureinfo query, so a non-elevated
    wxc-exec no longer misreports "not enabled".
  • Removed the old windows_sandbox_common::windows_sandbox_runner; wxc one-shot
    dispatch constructs WindowsSandboxRunner. The host daemon is dropped from the
    workspace members for this phase (re-added with the state-aware lifecycle in
    Phase 2); the dormant control_plane record/discovery functions are pub and
    compile clean for Phase 2 to build on.
  • Tests/docs: e2e test_windows_sandbox and the renamed
    run_windows_sandbox_one_shot_tests.ps1 drop the daemon pre-spawn and exercise
    the fresh-VM path. The full dual-mode backend-doc rewrites
    (windows-sandbox.md/reference.md, schema.md, state-aware API) are deferred to
    Phase 2, where they describe the end state; Phase 1 makes only minimal
    P1-accurate touches to copilot-instructions.md.

Tests

  • cargo check --workspace --all-targets, cargo clippy --workspace --all-targets -- -D warnings, and cargo fmt --all -- --check: clean.
  • cargo test: windows_sandbox_lifecycle 110, windows_sandbox_common 26, wxc 13,
    wxc_windows_sandbox_guest 8 -- all passed.
  • Verified the dropped daemon doesn't break the full build (build.bat's daemon
    copy is if exist-guarded) and that no source references the deleted runner.

Fixes #560

Microsoft Reviewers: Open in CodeFlow

…col (Phase 1)

This PR rewrites the Windows Sandbox one-shot backend onto a new
`windows_sandbox_lifecycle` crate and an authenticated host<->guest
protocol, and fixes the non-elevated feature-detection false negative
(#560). It is Phase 1 of the Windows Sandbox rewrite stack (stacked on
the Phase 0 shared-plumbing PR); the state-aware lifecycle + host daemon
and the SDK land in follow-up PRs.

Details

* New `windows_sandbox_lifecycle` crate: the transient one-shot
  `WindowsSandboxRunner` (`ScriptRunner`) plus the reusable VM lifecycle
  primitives (`vm`, `rendezvous`, `bridge`, `ipc_exec`, `policy`,
  `teardown`, `control_plane` host-VM-lock/ownership + Win32 `os` FFI).
* One-shot now launches a FRESH disposable VM per invocation with
  guaranteed teardown on every exit path (normal/panic, Ctrl-C/shutdown
  handler, and next-run reconcile) -- no warm-VM reuse. The legacy
  `experimental.windows_sandbox.idleTimeoutMs`/`daemonPipeName` fields are
  still parsed but ignored, with a stderr warning (suppress the per-call
  fresh-VM notice via `WXC_WSB_ACK_ONESHOT_FRESH_VM=1`).
* Authenticated protocol: `windows_sandbox_common::auth` adds a per-launch
  32-byte `Nonce` + 1-byte `ChannelRole` handshake on every TCP channel
  (boot + reconnect); the guest pairs accepted sockets by declared role,
  not accept order, defeating cross-user accept-race hijack. Guest agent
  rewritten (`listener`/`executor`/`job`/`firewall`) onto the new
  `sandbox_protocol` + auth.
* Fixes #560: feature detection is now by `WindowsSandbox.exe` presence
  instead of an elevated `dism /get-featureinfo` query, so a non-elevated
  `wxc-exec` no longer misreports "not enabled".
* Removed the old `windows_sandbox_common::windows_sandbox_runner`; wxc
  one-shot dispatch now constructs `WindowsSandboxRunner`. The host daemon
  is dropped from the workspace members for this phase (re-added with the
  state-aware lifecycle next); the dormant `control_plane` record/discovery
  functions are `pub` and compile clean for the follow-up to build on.
* Tests/docs: e2e `test_windows_sandbox` and the renamed
  `run_windows_sandbox_one_shot_tests.ps1` drop the daemon pre-spawn and
  exercise the fresh-VM path. The full dual-mode backend-doc rewrites
  (windows-sandbox.md/reference.md, schema.md, state-aware API) are
  deferred to the state-aware PR, where they describe the end state.

Tests

* `cargo check --workspace --all-targets`, `cargo clippy --workspace
  --all-targets -- -D warnings`, and `cargo fmt --all -- --check`: clean.
* `cargo test`: windows_sandbox_lifecycle 110, windows_sandbox_common 26,
  wxc 13, wxc_windows_sandbox_guest 8 -- all passed.
* Verified the dropped daemon doesn't break the full build (build.bat's
  daemon copy is `if exist`-guarded) and that no source references the
  deleted runner remain.

Fixes #560

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Generated-with: claude-opus-4.8
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.

1 participant