Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
artifact_name: release-x86_64-pc-windows-msvc

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Set up Rust (stable)
uses: actions-rust-lang/setup-rust-toolchain@v1
Expand Down Expand Up @@ -78,6 +78,11 @@ jobs:
- name: cargo build
run: cargo build

- name: Windows sandbox setup
if: matrix.os == 'windows-2022'
shell: pwsh
run: .\target\debug\mcp-repl.exe windows-sandbox setup

- name: Python public API suite
if: matrix.os != 'windows-2022'
run: python3 tests/run_integration_tests.py --binary target/debug/mcp-repl
Expand Down Expand Up @@ -179,7 +184,7 @@ jobs:
GH_TOKEN: ${{ github.token }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Download packaged artifacts
uses: actions/download-artifact@v4
Expand Down Expand Up @@ -321,7 +326,7 @@ jobs:
RELEASE_TAG: ${{ github.ref_name }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
ref: ${{ env.RELEASE_TAG }}
fetch-depth: 0
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,21 @@
url = "2.5.8"

[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.62.2", features = [
"Win32_Foundation",
"Win32_NetworkManagement_WindowsFilteringPlatform",
"Win32_NetworkManagement_WindowsFirewall",
"Win32_Security",
"Win32_System_Com",
"Win32_System_Rpc",
] }
windows-sys = { version = "0.61.2", features = [
"Win32_Foundation",
"Win32_Globalization",
"Win32_Security",
"Win32_Security_Cryptography",
"Win32_Security_Authorization",
"Win32_Security_Credentials",
"Win32_Storage_FileSystem",
"Win32_System_Console",
"Win32_System_IO",
Expand Down
18 changes: 13 additions & 5 deletions docs/plans/active/managed-network-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

- Add a macOS-first managed network proxy for workers.
- Keep existing full-network sandbox behavior unchanged when no managed domain rules are configured.
- Keep Linux and Windows as explicit follow-up phases with clear unsupported errors for managed domain enforcement.
- Keep Linux as an explicit follow-up phase with clear unsupported errors for managed domain enforcement.
- Windows uses a setup-backed offline account plus account-scoped firewall rules
and loopback WFP filters to route managed-domain traffic through the
server-owned proxy.

## Status

- State: active
- Last updated: 2026-05-01
- Current phase: Linux planning
- Last updated: 2026-06-19
- Current phase: Linux planning after Windows enforcement

## Current Direction

Expand All @@ -21,7 +24,8 @@
## Long-Term Direction

- Linux should route worker traffic through a server-owned proxy from inside the Linux sandbox without allowing direct egress.
- Windows should use the same policy surface once the Windows sandbox can route worker traffic through a managed proxy.
- Windows uses the same policy surface after `mcp-repl windows-sandbox setup`
installs the offline account, firewall rules, and loopback WFP filters.
- A future UI or approval flow can amend allow/deny rules, but this phase only supports static CLI/config rules.
- A future HTTP policy layer may support method restrictions such as "allow
GET but deny POST", but that is separate from the current host/domain
Expand All @@ -33,11 +37,14 @@
- Phase 0: completed - chose the managed proxy shape and enforcement boundary.
- Phase 1: completed - implemented macOS managed proxy and public tests.
- Phase 2: pending - Linux enforcement.
- Phase 3: pending - Windows enforcement.
- Phase 3: completed - Windows enforcement.

## Locked Decisions

- macOS enforcement uses Seatbelt loopback-only egress to the managed proxy ports.
- Windows enforcement uses a dedicated `McpReplOffline` local account,
account-scoped firewall block rules, loopback WFP filters, and fixed managed
proxy ports from setup.
- Domain policy is deny-first and allowlist-based.
- Supported patterns are exact hosts, `*.example.com`, and `**.example.com`.
- Exact URLs are rejected instead of being silently reduced to hosts.
Expand Down Expand Up @@ -73,3 +80,4 @@
- 2026-04-30: Scoped matching to host/domain patterns after deciding exact HTTPS URL filtering would require a separate MITM design.
- 2026-04-30: Implemented the macOS slice with a small in-process HTTP/SOCKS proxy in `src/managed_network.rs`, CLI/config validation for host patterns, and worker launch wiring that injects proxy env vars before Seatbelt policy rendering.
- 2026-05-01: Documented managed-network follow-up scenarios and tradeoffs for package, database, Shiny, local-service, and hardening workflows.
- 2026-06-19: Implemented the Windows slice with explicit elevated setup, DPAPI-protected offline account credentials, fixed proxy ports, firewall rules scoped to the offline account SID, loopback WFP filters for direct local socket blocking, and offline-wrapper launch for workspace-write no-network or managed-domain sandbox policies.
13 changes: 9 additions & 4 deletions docs/plans/active/windows-test-parity.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
## Status

- State: active
- Last updated: 2026-06-18
- Last updated: 2026-06-19
- Current phase: validation

## Current Direction

- Public end-to-end Rust tests now run on Windows where the product behavior is expected to match other platforms.
- Use normal Windows `cargo test` failures to identify real shared-state, host-dependency, or Windows launcher issues instead of preserving CI serialization as a workaround.
- Keep Windows-specific compatibility tests when they assert Windows-only process, console, sandbox, or path behavior.
- Windows public network-policy cases now require `mcp-repl windows-sandbox setup`
before the suite so the offline account, firewall rules, and loopback WFP
filters are present.

## Long-Term Direction

Expand All @@ -28,24 +31,24 @@
- Phase 0: completed - inventoried skipped Windows tests and CI serialization.
- Phase 1: completed - enabled skipped public R/Python tests where feasible.
- Phase 2: completed - removed Windows-only CI serialization after local validation.
- Phase 3: pending - decide whether Windows managed-network enforcement should close the remaining external public API skips.
- Phase 3: completed - Windows managed-network enforcement closes the remaining external public API network skips.

## Locked Decisions

- Public end-to-end integration tests should exercise the same MCP surface across platforms unless the tested behavior is genuinely platform-specific.
- Cargo discovery should remain the source of truth for Rust integration tests.
- Windows test target names must avoid installer/update keywords that trigger UAC installer detection for test executables.
- Standalone ConPTY terminal mode toggles are snapshot noise and should be normalized out of shared snapshots.
- Windows no-network and managed-domain sandbox tests depend on the explicit
offline-account setup command rather than silently weakening enforcement.

## Open Questions

- Whether Windows managed-network/domain enforcement should be implemented so the external workspace-write network allow/block cases can run instead of reporting unsupported platform skips.
- Whether optional reticulate help coverage should gain a Windows-specific server fix for hosts where reticulate initializes under `Rscript` but hangs inside the MCP R worker.
- Whether the shared Windows suite server startup mutex is still necessary now that live test sessions pass under ordinary Cargo scheduling.

## Next Safe Slice

- Investigate Windows managed-network enforcement for the external public API suite, or prove it should remain a documented unsupported sandbox feature.
- Investigate the reticulate Windows MCP-worker initialization hang separately from test scheduling.

## Stop Conditions
Expand All @@ -61,3 +64,5 @@
- 2026-06-18: Removed Windows-only CI serialization after `cargo test --quiet` passed locally under normal Cargo scheduling.
- 2026-06-18: Renamed Rust test targets containing `install` or `updates` because Windows UAC installer detection can refuse to launch those test executables with `os error 740`.
- 2026-06-18: Kept external public API network policy cases as unsupported on Windows because managed/domain network enforcement is not implemented there yet.
- 2026-06-19: Added Windows sandbox setup to CI and removed the Windows skips
from the external public API workspace-write network allow/block cases.
24 changes: 22 additions & 2 deletions docs/sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,28 @@ Optional `bwrap` stage:
- Python support is not part of the stable Windows surface yet. The embedded
backend no longer requires a Unix PTY, but Windows support still depends on
the selected CPython installation exposing a loadable runtime library.
- managed domain allowlists are not enforced on Windows yet; configuring allowed
or denied domains with enabled network access currently fails closed.
- workspace-write network-restricted and managed-domain Windows sandboxes require one-time
elevated setup:

```powershell
mcp-repl windows-sandbox setup --http-proxy-port 39080 --socks-proxy-port 39081
```

Setup creates or refreshes the local non-admin `McpReplOffline`
account, stores its password with current-user DPAPI protection under
`%LOCALAPPDATA%\mcp-repl\windows-sandbox\`, installs outbound firewall
block rules scoped to that account SID, and installs persistent loopback
WFP filters for the configured proxy-port exceptions.
- `workspace-write` with `network_access=true` and no managed domain rules keeps
the current-user sandbox path and allows network access normally.
- default `workspace-write` and managed-domain `workspace-write` launches run
the Windows wrapper through the offline account. Firewall rules block
non-loopback outbound traffic, and WFP filters block direct loopback TCP/UDP
traffic except the configured managed proxy TCP ports.
- when allowed or denied domains are configured on Windows, the server starts
the same managed HTTP/SOCKS proxy used on macOS on the fixed setup ports and
injects proxy env vars into the worker. Missing setup, stale setup, or occupied
fixed proxy ports fail closed with an actionable error.
- `read-only` and `workspace-write` use a two-stage Windows sandbox model:
- the parent prepares and reuses stable filesystem ACL state for the effective sandbox policy,
- the internal Windows wrapper requires prepared launch state and applies launch-scoped ACLs for the worker run.
Expand Down
Loading
Loading