Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1ebc297
feat(mxc): ETW->OCSF audit consumer + Windows OCSF JSONL parity (cp6 P1)
jamieknvidia Jul 9, 2026
75f667a
feat(mxc): map remaining Sandboxing ETW events to OCSF
jamieknvidia Jul 9, 2026
8b9c423
fix(mxc): seed ETW attribution under registry lock + Device tests
jamieknvidia Jul 9, 2026
9467b46
fix(mxc-etw): buffer+replay racing events and harden attribution keys
jamieknvidia Jul 14, 2026
5efe3cd
docs(mxc-etw): note cmd_line is captured raw with no privacy filtering
jamieknvidia Jul 14, 2026
65bb41f
fix(mxc-etw): open ETW trace on caller thread so start_session report…
jamieknvidia Jul 14, 2026
b28465c
fix(mxc-etw): guard pending-event replay against PID recycling
jamieknvidia Jul 14, 2026
661270a
fix(mxc-etw): surface unexpected ProcessTrace termination (review #4)
jamieknvidia Jul 14, 2026
26fd113
feat(mxc-ocsf): add ETW->OCSF audit-trail example kit; fix proxy-con…
jamieknvidia Jul 15, 2026
3e46489
feat(mxc-ocsf): clearer audit report + client-safe run-ocsf-audit.ps1
jamieknvidia Jul 16, 2026
82575c5
Implement Windows host proxy integration and update dependencies for …
araza008 Jul 1, 2026
a6b2f34
Update README and gateway config to clarify egress proxy address hand…
araza008 Jul 7, 2026
56cf1e8
Refactor ProxyIdentityMode to return Result for static_binary and add…
araza008 Jul 8, 2026
9b0e989
Enhance platform_hosts_path for Windows to use SystemRoot and improve…
araza008 Jul 8, 2026
582364a
Refactor FileFingerprint to use Option for mtime and ctime, simplifyi…
araza008 Jul 9, 2026
8e6561b
Add conditional compilation for Windows host module
araza008 Jul 9, 2026
6c58abb
add unit tests for OPA policy evaluation and identity handling
araza008 Jul 14, 2026
1984815
remove openshell-supervisor-network from unsupported driver package t…
araza008 Jul 15, 2026
2938361
feat(mxc): enable host proxy TLS state generation
araza008 Jul 22, 2026
9669278
fix(docs): remove outdated notes on governed egress from docs
araza008 Jul 22, 2026
938bb66
fix(tests): update TLS environment variable paths to use temporary di…
araza008 Jul 22, 2026
e891d4d
fix(examples): make run-mxc-e2e harness correct and orphan-free
jamieknvidia Jul 16, 2026
df7852d
fix(e2e): probe timeout is milliseconds (10ms->30000ms)
jamieknvidia Jul 16, 2026
122b77c
fix(mxc): use native paths in real runtime probes
shailendra-nv Jul 21, 2026
5d5956e
fix(mxc): make processcontainer work with mxc-latest-released wxc-exec
pkhodade-NV Aug 12, 2026
7be6327
fix(e2e): address CodeRabbit review on run-mxc-e2e.ps1 (MR !46)
jamieknvidia Jul 16, 2026
d1ac66b
feat(mxc-e2e): collect run-mxc-e2e output into a results bundle
pkhodade-NV Jul 16, 2026
296761e
fix(mxc-e2e): address CodeRabbit review on run-mxc-e2e.ps1
pkhodade-NV Jul 16, 2026
555e872
fix(examples): pass gateway config via OPENSHELL_GATEWAY_CONFIG for s…
jamieknvidia Jul 17, 2026
81adeec
fix(compute): [regression 662dee68] MXC sandbox stuck in Provisioning…
pkhodade-NV Aug 3, 2026
99c9f74
fix(run-mxc-e2e): improve scoring logic and enhance command execution…
araza008 Sep 3, 2026
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
5 changes: 5 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ terminal-colorsaurus = "1.0"
# Error handling
miette = { version = "7", features = ["fancy"] }
thiserror = "2"

# Windows platform APIs (ETW/TDH audit consumer in openshell-driver-mxc; Windows-only)
windows = { version = "0.62", features = ["Win32_Foundation", "Win32_System_Diagnostics_Etw", "Win32_System_Time"] }
anyhow = "1"

# Logging/Tracing
Expand Down
9 changes: 9 additions & 0 deletions crates/openshell-driver-mxc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ name = "openshell_driver_mxc"

[dependencies]
openshell-core = { path = "../openshell-core" }
# OCSF builders + emit target used by the Windows ETW audit consumer. OS-agnostic
# crate (no windows deps), so safe to depend on from all targets; only the
# windows-gated `etw_consumer` module actually uses it.
openshell-ocsf = { path = "../openshell-ocsf" }
tokio = { workspace = true }
tonic = { workspace = true }
futures = { workspace = true }
Expand All @@ -26,6 +30,11 @@ tracing = { workspace = true }
thiserror = { workspace = true }
uuid = { workspace = true }

# ETW/TDH real-time consumer and host CONNECT proxy integration.
[target.'cfg(target_os = "windows")'.dependencies]
openshell-supervisor-network = { path = "../openshell-supervisor-network" }
windows = { workspace = true }

[dev-dependencies]
tokio = { workspace = true }
# tempfile is not a workspace dependency; 3.27 is already resolved in Cargo.lock.
Expand Down
56 changes: 43 additions & 13 deletions crates/openshell-driver-mxc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ readiness; there is no in-sandbox supervisor or `ConnectSupervisor` relay.

## Capability Matrix

| Capability | MXC driver |
|---|---|
| Filesystem policy | Read-only/read-write grants come only from `SandboxPolicy`. `process_container` enforces default-deny; `isolation_session` is an explicit grant-only compatibility mode. |
| Network policy | Rejected synchronously during sandbox creation until an enforcing egress path is bound. |
| Process policy | Unsupported; MXC supplies OS isolation only. |
| Interactive exec/connect/forward | Unsupported; the configured workload runs in-driver. |
| Restart durability | Unsupported; the in-memory registry cannot recover live sessions. |
| Capability | MXC driver | Closing it requires |
|---|---|---|
| Filesystem policy (read-write / read-only grants) | ✅ provision-time AppContainer shares | — |
| Governed egress (CONNECT proxy + OPA + L7) | Available behind `egress_proxy` on `process_container`; the driver starts a per-sandbox host CONNECT proxy, generates HTTPS MITM trust material, and injects the CA bundle into the sandbox process env | Gateway event-bus wiring follow-on |
| Network policy | Split into MXC `network.proxy` + trimmed OpenShell policy on `process_container`; `isolation_session` still rejects network config | MXC feedback item M1 for persistent sessions |
| Process policy (seccomp, uid/gid) | ❌ host-side governance design; OS isolation only | not pursued |
| Interactive exec/connect/forward | ❌ exec runs in-driver, no client attach | gateway interactive-exec surgery (follow-on) |
| Bundled agent image | ❌ no OCI image; relies on Windows host install | — |
| Restart durability | ❌ in-memory registry; restart orphans live sessions | follow-on |
| Concurrent sandboxes | ⚠️ isolation_session v1 is single-session | MXC backend feature |

The filesystem enforcement proof has two paths:

Expand All @@ -38,9 +41,17 @@ backend = "process_container"
default_configuration_id = "composable"
pc_least_privilege = false
pc_capabilities = []
# Pattern-C governed egress. The address is a loopback seed; each sandbox
# receives a unique ephemeral proxy port.
egress_proxy = false
egress_proxy_addr = ""
debug = false
```

When `egress_proxy` is enabled, `egress_proxy_addr` must be a loopback
`IP:PORT` seed. The driver preserves the configured IP and allocates a unique
ephemeral port for each sandbox's `network.proxy` redirect.

Supply workload settings for each sandbox. The public config is keyed by driver name; the gateway forwards only the inner `mxc` object to the driver:

```powershell
Expand All @@ -51,7 +62,7 @@ openshell sandbox create --name mxc-demo --policy demo.yaml `

The `command` array is required and preserves Windows argument boundaries. `cwd` is optional. Environment variables come from the standard sandbox and template environment maps; the driver never copies values from the gateway host environment.

Network policy and live policy replacement or merge updates are rejected while the gateway uses MXC. Delete and recreate the sandbox to apply a different filesystem policy.
The host CONNECT proxy enforces network policy when governed egress is enabled. Live policy replacement or merge updates remain unsupported; delete and recreate the sandbox to apply a different policy.

## Prerequisites (live runs)

Expand All @@ -66,9 +77,25 @@ no isolation session needed), set `OPENSHELL_MXC_MOCK_WXC=1`.

The production driver maps the typed `SandboxPolicy` to MXC configuration before it inserts a registry entry or invokes `wxc-exec`. Mapping failure therefore returns from `CreateSandbox` without leaving a partial sandbox.

`EmbeddedPolicyMapper` calls the embedded [`policy_map`](src/policy_map/) module directly and normalizes filesystem paths to Windows form. It does not add gateway-configured host paths. The policy supplied for the sandbox is the only source of filesystem grants.

The mapper retains an internal policy-splitting seam for future development, but the runtime exposes no governed-egress switch. Any network rule fails closed until an enforcing proxy is implemented and bound to the sandbox lifecycle.
When `egress_proxy` is enabled, `EmbeddedPolicyMapper` uses `split_policy`
instead: MXC receives filesystem grants plus a loopback `network.proxy`
redirect, and the driver starts a host CONNECT proxy from the trimmed
network-only `SandboxPolicy`. The proxy uses the configured agent command as
the static sandbox process identity because MXC does not expose Linux-style
procfs socket ownership. For HTTPS L7 inspection, the host proxy generates a
per-sandbox CA and injects `NODE_EXTRA_CA_CERTS`, `DENO_CERT`, `SSL_CERT_FILE`,
`REQUESTS_CA_BUNDLE`, `CURL_CA_BUNDLE`, and `GIT_SSL_CAINFO` into the agent
process env. It does not add the generated CA directory to MXC read-only grants:
released `wxc-exec` BaseContainer builds require `WRITE_DAC` on every such
grant and reject the user-owned proxy temp directory. The driver seeds only
`SYSTEMROOT`, `WINDIR`, `PATH`, `COMSPEC`, and `LOCALAPPDATA` from the gateway
host before applying sandbox and TLS overrides, so required Windows bootstrap
values remain available without exposing the gateway's full environment. The
development export surface remains the
[`policy-to-mxc`](examples/policy-to-mxc.rs) example; there is no production
`openshell policy export-mxc` subcommand yet.

If governed egress is disabled, any network rule fails closed rather than launching without an enforcement path.

Parity and matrix tests under [`tests/`](tests/) cover the mapper on the Windows MSVC lane. The driver performs this mapping automatically; there is no separate policy-export command or example.

Expand Down Expand Up @@ -98,6 +125,10 @@ exits 0 rather than failing.
and a `verdicts` object). Run it before the real-MXC lane to understand what
will PASS vs SKIP on a given host:

The probe uses a unique, user-owned Windows temp directory for every run.
MXC treats config paths literally (it does not expand `%TEMP%`), and the
per-run directory keeps AppContainer+DACL fallback mutations narrowly scoped.

```powershell
powershell -NoProfile -ExecutionPolicy Bypass `
-File crates/openshell-driver-mxc/examples/probe-mxc-host.ps1
Expand All @@ -112,7 +143,6 @@ velocity keys not enabled, isolation_session absent).

## Deferred work

- **Interactive exec/connect/forward** → `adapt-openshell-gateway-windows`
- **Governed egress** remains fail-closed until an enforcing proxy is implemented and bound to sandbox lifecycle.
- **Interactive exec/connect/forward** — gateway interactive-exec surgery (follow-on)
- **Restart durability** (deprovision orphaned sessions on startup) → follow-on
- **GPU passthrough** → not pursued in host-side-governance design
77 changes: 77 additions & 0 deletions crates/openshell-driver-mxc/examples/README-ocsf-audit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
OpenShell MXC - ETW -> OCSF audit-trail example
===============================================

WHAT THIS PROVES / PRODUCES
The full Windows OCSF audit path on this box:
gateway -> MXC driver -> process_container sandbox
-> the OS "Sandboxing" ETW provider fires as the sandbox is created
-> the gateway's in-process consumer decodes each event, attributes it to
an OpenShell sandbox_id, and maps it to OCSF
-> events are written to a durable JSONL audit log AND printed as
human-readable shorthand.

The deliverable is the OCSF log: openshell-ocsf.<date>.log, one OCSF event
object per line - the same schema and medium the Linux OpenShell pipeline
produces (Windows is at functional parity).

OCSF classes you will see:
[6002] Application Lifecycle - sandbox created
[5019] Device Config State Change - OS policy / hardening / proxy / console
[1007] Process Activity - in-sandbox process launch (+ cmd line)
[2004] Detection Finding - MXC setup activity errors (informational)

PREREQUISITES (on this test box)
- wxc-exec.exe present (default expected: C:\mxc-kit\bin\wxc-exec.exe)
- process_container backend live (it was for our earlier runs)
- Run ELEVATED (Run as administrator) OR from an account in the
'Performance Log Users' group. Opening the real-time ETW session needs this;
without it the run fails fast with a clear message.

HOW TO RUN
1. Open an ELEVATED PowerShell in THIS folder.
2. Run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\run-ocsf-audit.ps1
If wxc-exec is somewhere else:
... -File .\run-ocsf-audit.ps1 -WxcExecPath "D:\path\to\wxc-exec.exe"

WHAT YOU GET BACK
The script prints PASS/FAIL + an event-type coverage count and class breakdown,
points you at the OCSF audit log, and creates:
results-<timestamp>.zip
It contains the OCSF audit log (openshell-ocsf.<date>.log), the full transcript,
the gateway logs (with the human-readable OCSF shorthand), a summary, and the
exact config + policy used. To auto-copy the bundle to a shared location, pass
-ShareOut '\\server\share' (off by default; results stay local otherwise).

FILES IN THIS PACKAGE
openshell-gateway.exe the gateway (self-contained; needs only VC++ runtime)
openshell.exe the CLI
mxc-ocsf-audit.toml gateway/driver config (process_container, etw_audit=true, egress proxy)
ocsf-audit.yaml sandbox policy (read-write grant to the share dir)
run-ocsf-audit.ps1 the orchestrator you run
README-ocsf-audit.txt this file
(wxc-exec.exe is used IN PLACE on the box; not shipped)

USEFUL OPTIONS
-SandboxCount <n> Create n sandboxes (default 2). More sandboxes = more events.
-NoProxy Skip the per-sandbox egress proxy. This omits ONLY the
SandboxProxyConfigured config event; everything else is
still produced. (Default is proxy ON for the full set.)
-WxcExecPath <path> Path to wxc-exec.exe on this box.
-ShareOut <path> Copy the results bundle to a shared location
(e.g. \\server\share). Off by default (results stay local).
-KeepRunning Leave the gateway running afterward for inspection.

NOTES
- The control plane between CLI and gateway runs with --disable-tls on loopback;
that is unrelated to the OCSF audit path this example exercises.
- A "supervisor session not connected" / ssh 255 message during sandbox create
is EXPECTED on MXC and harmless - the agent already ran in-driver.
- The proxy path requires the host-side CONNECT proxy and an absolute agent
binary (the packaged config uses C:\Windows\System32\cmd.exe); the run script
handles this for you.
- The Sandboxing provider reports the sandbox entry-point process, not the full
in-sandbox process tree. Deep process-tree auditing would need a second ETW
source (Microsoft-Windows-Kernel-Process) and is out of scope for this trail.
- cmd_line is captured verbatim into OCSF process.cmd_line with no redaction on
this path; treat the audit log as sensitive at rest and in transit.
54 changes: 54 additions & 0 deletions crates/openshell-driver-mxc/examples/mxc-ocsf-audit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# MXC gateway config for the ETW -> OCSF audit-trail example.
#
# Goal: exercise the in-process ETW consumer (Plane A) end-to-end so that
# creating a sandbox produces a full OCSF audit trail — Application Lifecycle
# [6002], Device Config State Change [5019], Process Activity [1007] and
# Detection Finding [2004] — written to a durable JSONL log, just like the Linux
# OCSF pipeline.
#
# run-ocsf-audit.ps1 patches wxc_exec_path, backend, etw_audit, the egress-proxy
# switch and agent_command into a disposable copy of this file, so the values
# here are sane defaults; edit them if you run the gateway directly.

[openshell.drivers.mxc]
# Path to wxc-exec.exe on the box (patched by the run script; default is the
# location observed on the MXC test boxes).
wxc_exec_path = "C:\\mxc-kit\\bin\\wxc-exec.exe"

# One-shot AppContainer. This is the backend whose Sandboxing ETW the consumer
# captures. (isolation_session is "dark" — it emits no provider events.)
backend = "process_container"

default_configuration_id = "composable"

# Host folder mapped read-write into the sandbox.
share_dir = "C:/work/openshell-mxc-demo"
agent_cwd = "C:/work/openshell-mxc-demo"

# A simple in-policy write — enough to make wxc-exec provision an AppContainer and
# drive the Sandboxing provider. Absolute cmd.exe path is REQUIRED when the egress
# proxy is on (the host proxy hashes agent_command[0] as its static identity
# binary, so it must be an absolute, existing exe).
agent_command = [
"C:\\Windows\\System32\\cmd.exe",
"/c",
"echo hello from openshell ocsf audit 1>C:\\work\\openshell-mxc-demo\\hello.txt",
]

debug = false

# Turn ON the Plane-A ETW -> OCSF audit consumer. This is the core of the example.
etw_audit = true

# Per-sandbox governed egress. Enabling this makes the driver start a host CONNECT
# proxy and hand MXC a `network.proxy` redirect, which is what makes MXC emit the
# SandboxProxyConfigured event — the config event mapped to OCSF CONFIG [5019]
# that completes full event coverage. Requires backend = process_container and a
# loopback (127.0.0.1) seed address; the driver allocates a unique ephemeral port
# per sandbox from this seed. Run-ocsf-audit.ps1 disables this when passed
# -NoProxy.
egress_proxy = true
egress_proxy_addr = "127.0.0.1:18080"
19 changes: 19 additions & 0 deletions crates/openshell-driver-mxc/examples/ocsf-audit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# ocsf-audit.yaml — sandbox policy for the MXC ETW -> OCSF audit-trail example.
#
# Minimal filesystem policy granting the shared host folder read-write; everything
# else is default-deny. The granted path MUST match `share_dir` /
# OPENSHELL_MXC_SHARE_DIR in mxc-ocsf-audit.toml.
#
# No network_policies block is needed here: the per-sandbox egress proxy is driven
# by `egress_proxy = true` in mxc-ocsf-audit.toml (that is what makes MXC emit the
# SandboxProxyConfigured event we map to OCSF), not by a policy rule.
version: 1

filesystem_policy:
include_workdir: false
read_only: []
read_write:
- "C:/work/openshell-mxc-demo"
24 changes: 19 additions & 5 deletions crates/openshell-driver-mxc/examples/probe-mxc-host.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ $pcTrialMessage = "wxc-exec not found"
$isoTrialResult = "absent"
$isoTrialMessage = "wxc-exec not found"

$probeTempPath = Join-Path ([System.IO.Path]::GetTempPath()) ("openshell-mxc-probe-" + [Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $probeTempPath | Out-Null

try {
if ($wxcInfo.exists) {
# --probe
$probeResult = Invoke-WxcProbe -wxc $WxcExecPath
Expand All @@ -131,11 +135,11 @@ if ($wxcInfo.exists) {
containment = "processcontainer"
process = @{
commandLine = "cmd /c exit 0"
cwd = "%TEMP%"
cwd = $probeTempPath
timeout = 0
}
filesystem = @{
readwritePaths = @("%TEMP%")
readwritePaths = @($probeTempPath)
}
}
$dryResult = Invoke-WxcDryRun -wxc $WxcExecPath -config $dryConfig
Expand All @@ -149,15 +153,22 @@ if ($wxcInfo.exists) {
containment = "processcontainer"
process = @{
commandLine = "cmd /c exit 0"
cwd = "%TEMP%"
timeout = 10
cwd = $probeTempPath
timeout = 30000
}
filesystem = @{
readwritePaths = @("%TEMP%")
readwritePaths = @($probeTempPath)
}
processContainer = @{
leastPrivilege = $false
}
# cmd.exe needs the Win32k calls represented by disable = false.
# Filesystem and network restrictions remain default-deny.
ui = @{
disable = $false
clipboard = "none"
injection = $false
}
}
$pcResult = Invoke-WxcPhase -wxc $WxcExecPath -config $pcConfig
$pcOutput = $pcResult.Output
Expand Down Expand Up @@ -260,6 +271,9 @@ if ($wxcInfo.exists) {
$isoTrialMessage = "exit $($isoResult.ExitCode): $isoOutput"
}
}
} finally {
Remove-Item -LiteralPath $probeTempPath -Recurse -Force -ErrorAction SilentlyContinue
}

# ── Verdicts ──────────────────────────────────────────────────────────────────

Expand Down
Loading
Loading