fix(isolation-session): refuse network policy the backend cannot enforce; require the unrestricted-network acknowledgment - #682
Open
adpa-ms wants to merge 8 commits into
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
jeffstall
approved these changes
Jul 25, 2026
The IsolationSession container runs on an unrestricted network (outbound open; a process inside can listen on a localhost-reachable port) that MXC cannot filter or deny. Previously the backend accepted the default `Block` network policy, silently affirming a deny it cannot enforce. Now provision (and one-shot, which runs the full lifecycle) accept ONLY the canonical unrestricted-network acknowledgment: network.defaultPolicy=allow + allowLocalNetwork=true, no allowed/blocked hosts, no proxy, default enforcement. Everything else (including an absent policy, which defaults to the unenforceable `Block`) is refused. Post-provision phases reject any supplied network policy (fixed at provision) via a new domain `ExecutionRequest.network_specified` flag set from wire `network` presence in config_parser; an absent policy is inherited. This closes the domain-model blind spot where an explicit default-valued `Block` is indistinguishable from absent. Reworded the network/proxy error messages and added a post-provision "immutable" message. Updated the happy-path iso test configs to the canonical form; post-provision and negative-path configs are intentionally unchanged. Gates: cargo fmt --check; clippy --all-features; cargo test iso ON and OFF (wxc_common + isolation_session_common green, 84 iso + 456 wxc_common); parser network_specified tests; wxc_host_prep 16 passed (elevated). Pre-existing env failures (microvm e2e staging) are identical iso ON/OFF and unrelated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
Mirror the Rust-side IsolationSession network fix in the TypeScript SDK.
`IsolationSessionProvisionConfig.network` is now a required field typed as
the exact literal `{ defaultPolicy: 'allow'; allowLocalNetwork: true }`, so
the caller must explicitly acknowledge that the isolation session container
runs on an unrestricted network the backend cannot filter or deny. Any other
value (or a wrong-typed one) is a compile error; the post-provision configs
intentionally expose no `network` field, so the type system enforces the
provision-only rule for SDK callers.
Tests: type-level @ts-expect-error assertions (required network; block and
allowLocalNetwork=false rejected; network rejected on post-provision configs);
provisionSandbox lifts the canonical network to the envelope top level;
updated the conformance oracle's LiftedPhaseKey and the integration test's
provision calls. npm run build + npm test green (207 tests).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
Update the in-repo docs to match the new behavior: the backend still rejects all filesystem policy (no host-folder-sharing primitive), but the network policy is now honesty-gated. Provision (and one-shot) require the canonical unrestricted-network acknowledgment (network.defaultPolicy=allow + allowLocalNetwork=true, no host rules, no proxy, default enforcement) and refuse anything else, including an absent policy; post-provision phases reject any supplied network policy and inherit an absent one. Touches: copilot-instructions iso backend row; docs/isolation-session/oneshot (policy-validation coverage row) + state-aware-rust (prose + policy matrix) + state-aware-typescript (provision config table gains the required `network` field); sdk/node/README state-aware example now passes the acknowledgment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
Add end-to-end and integration tests for the new network-acknowledgment behavior, and fix a latent bug the required-network change introduced in the SDK E2E probe. Fix (critical): `probeStateAwareRuntime` (the module-load skip probe in the SDK integration suite) provisioned iso with no config. With `network` now required at provision, that returns `policy_validation`, which the probe rethrows — so on an iso-capable host the whole integration suite would error at load instead of running. The probe now passes the canonical network acknowledgment for iso. New integration tests (sdk/node integration, real wxc-exec): the backend refuses a provision that (a) omits the network acknowledgment, (b) sends a non-canonical network (defaultPolicy=block), or (c) omits allowLocalNetwork — each via an untyped call, proving the runtime guard holds even when a JS caller bypasses the compile-time type. New E2E tests (PowerShell VM suites): one-shot refuses block / allow-without- allowLocalNetwork / allowedHosts; state-aware refuses a non-canonical network at provision and refuses any network policy on the start and exec post-provision phases (even the canonical acknowledgment, since it is immutable post-provision). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
The IsolationSession TTY resize smoke (run_isolation_session_resize_smoke.ps1) builds its wxc-exec config inline and was the one manual (-Manual-only) test not covered by the automated suite, so it was missed when the network-acknowledgment requirement landed. Without a network block the backend now rejects it with policy_validation. Add the canonical {defaultPolicy:allow, allowLocalNetwork:true} form (matching isolation_session_powershell_interactive.json) so the manual smoke provisions again.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
…policy
The cross-backend state-aware design docs and the v2 GA networking scope doc still described IsolationSession as honoring filesystem (not network) at provision, and showed provision examples using network.allowedHosts -- all now rejected by the backend. Align them with shipped behavior and the SDK type: provision honors only the canonical unrestricted-network acknowledgment ({ defaultPolicy: 'allow', allowLocalNetwork: true }); filesystem policy is rejected and ui is ignored.
- networking.md: reword the IsolationSession network-scope line (requires the canonical ack; rejects everything else).
- mxc-state-aware-sandbox-api.md / -overview.md: fix the 10.3 honor matrix (iso filesystem applied->rejected, ui applied->ignored), the SDK-exposure prose, the IsolationSessionProvisionConfig type (required network literal; drop filesystem and ui), and the provision examples (drop filesystem, allowedHosts->allowLocalNetwork).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
…ts, policy.ui gap state_aware.rs: the block comment above the validate_<phase> hooks still said network policy was rejected at every phase. That stopped being true when provision started accepting the canonical unrestricted-network acknowledgment. Correct the network clause while keeping the statements that are still true (the backend has no network primitive; proxy policy is rejected at every phase). oneshot.md: drop the Test Plan Count column and the '~31 backend-specific' / '287 total currently passing' figures. They were already stale (policy.rs has 28 tests, listed as ~24) and the rows never summed to the stated total. No other backend doc or README tracks test counts, so removing them makes this doc consistent and deletes a number that silently rots whenever a test is added. The durable Category / Location / What-it-verifies content stays. state-aware-rust.md: policy.ui was documented as rejected at every phase, but the backend never validates it, so a supplied UI policy is silently ignored. Correct the matrix to 'ignored' (matching the runtime and the state-aware design doc) and add an explicit known-gap note -- this is the same false-guarantee shape the network honesty gate closes, so rejecting policy.ui is the intended end state, not a deliberate exemption. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
adpa-ms
force-pushed
the
user/adibpa/copilot-iso-network-policy
branch
from
July 27, 2026 01:39
b9f2454 to
5f71027
Compare
bbonaby
reviewed
Jul 27, 2026
ionvasilian
approved these changes
Jul 27, 2026
Addresses PR review feedback: the presence signal describes the content of the policy object, not the invocation, so it belongs beside the other parse-derived policy member (`#[serde(skip)] network_proxy`) rather than next to ExecutionRequest's invocation flags (experimental_enabled, testing_features_enabled, dry_run, audit). Behavior-preserving: the flag is still captured once in the parser (`convert_wire_config`), which is also the path `mxc_engine::build_request` round-trips through, so the Rust SDK / FFI / C# callers are unaffected. `#[serde(skip)]` keeps it off the wire, so the schema and generated SDK types are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 47662115-cf22-4564-8930-370dfbee63fb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📖 Description
The IsolationSession backend has no primitive to filter or deny the container's network (outbound is open; a process inside can listen on a localhost-reachable port). It nonetheless silently accepted a default-deny /
Blockpolicy — plus host allowlists and proxies — it could not enforce, giving callers a false guarantee. This makes the backend honest:network.defaultPolicy = allowandnetwork.allowLocalNetwork = true, no host lists, no proxy. Anything else is refused with a clearpolicy_validationerror.ExecutionRequest.network_specifiedflag distinguishes an explicitblockfrom an absent policy).IsolationSessionProvisionConfig.networkis now a required literal, so callers acknowledge the unrestricted network at compile time.feature/isolation-session-internal, which already carries breaking changes for this backend.🔍 Validation
cargo fmt/cargo clippy --all-targets --all-features -D warningsclean;cargo testgreen withisolation_sessionON and OFF.policy.rsvalidators restructured with a full unit matrix (canonical accept, every refusal shape, proxy refusal, post-provision immutability, precedence).npm testandvalidate-configs.jsgreen.✅ Checklist
📋 Issue Type
Microsoft Reviewers: Open in CodeFlow