Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2015c2b
feat(mxc): ETW->OCSF audit consumer + Windows OCSF JSONL parity (cp6 P1)
jamieknvidia Jul 9, 2026
337dc8f
feat(mxc): map remaining Sandboxing ETW events to OCSF
jamieknvidia Jul 9, 2026
2ae8620
fix(mxc): seed ETW attribution under registry lock + Device tests
jamieknvidia Jul 9, 2026
e28cffe
fix(mxc-etw): buffer+replay racing events and harden attribution keys
jamieknvidia Jul 14, 2026
416be51
docs(mxc-etw): note cmd_line is captured raw with no privacy filtering
jamieknvidia Jul 14, 2026
65647db
fix(mxc-etw): open ETW trace on caller thread so start_session report…
jamieknvidia Jul 14, 2026
2251252
fix(mxc-etw): guard pending-event replay against PID recycling
jamieknvidia Jul 14, 2026
6a9f3db
fix(mxc-etw): surface unexpected ProcessTrace termination (review #4)
jamieknvidia Jul 14, 2026
8bde61c
feat(mxc-ocsf): add ETW->OCSF audit-trail example kit; fix proxy-con…
jamieknvidia Jul 15, 2026
6ca7343
feat(mxc-ocsf): clearer audit report + client-safe run-ocsf-audit.ps1
jamieknvidia Jul 16, 2026
5cdf440
fix(mxc): configure OCSF audit workloads per sandbox
araza008 Sep 8, 2026
6f05a7d
fix(mxc): omit command arguments from OCSF audit logs
araza008 Sep 8, 2026
64f6325
feat(etw): enhance ETW session management with distinct naming for co…
araza008 Sep 8, 2026
28281e4
fix(etw): bound the audit queue during overload
araza008 Sep 8, 2026
f98aede
fix(etw): harden sandbox audit attribution
araza008 Sep 8, 2026
48b1043
chore(mxc): address rebase follow-ups
drew Sep 8, 2026
13185f6
fix(mxc): align OCSF audit example with driver config
araza008 Sep 9, 2026
742fc56
fix(etw): redact command-line secrets in DecodedEtwEvent summary
araza008 Sep 9, 2026
043415d
fix(etw): enhance PID resolution and event attribution logic for ETW …
araza008 Sep 9, 2026
21b4c4a
fix(ocsf): restrict gateway-local JSONL sink to Windows/MXC path with…
araza008 Sep 9, 2026
ef0f3eb
address rebase issues
araza008 Sep 9, 2026
0ba0dfe
fix(mxc): address ETW audit review feedback
drew Sep 10, 2026
f443a0a
Merge branch 'main' into akberr/etw-to-ocsf-mapping
araza008 Sep 10, 2026
f6c029f
fix(mxc): resolve main merge conflicts and OCSF integration
drew Sep 11, 2026
ce4220a
fix(mxc): fail closed across ambiguous PID reuse
drew Sep 11, 2026
333c114
chore: merge main into MXC audit branch
drew Sep 11, 2026
ac559fe
fix(mxc): bind ETW attribution to process generation
drew Sep 11, 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
3 changes: 3 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 = ["Wdk_System_Threading", "Win32_Foundation", "Win32_System_Diagnostics_Etw", "Win32_System_Time"] }
anyhow = "1"

# Logging/Tracing
Expand Down
16 changes: 16 additions & 0 deletions architecture/security-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,19 @@ record for the same request.

Never log secrets, credentials, bearer tokens, or query parameters in OCSF
messages. OCSF JSONL output may be shipped to external systems.
The gateway-local OCSF JSONL file sink is restricted to the Windows/MXC path
and requires an explicit `OPENSHELL_OCSF_JSON=1` opt-in. Other gateway
deployments do not initialize this gateway file sink; a cross-platform gateway
sink requires its own storage and configuration integration.
MXC ETW process events record executable identity but omit command-line
arguments from structured fields and messages. Raw ETW debug summaries replace
the `commandLine` value with `[REDACTED]`, including pending-buffer eviction
diagnostics.
MXC ETW attribution never treats command text as ownership evidence. It uses the
driver-owned `wxc-exec` PID plus its kernel process start key as the initial
anchor. ETW attaches that generation key to each record, and the driver queries
the same key from its child process handle. PID attribution requires both values
to match, so reuse cannot transfer ownership between process generations.
Retired PID evidence is discarded; established identity, activity, and
correlation-vector links remain eligible during the five-second late-event
window. Records without matching generation evidence fail closed.
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", default-features = false }
# 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 (Plane A audit). Windows-only so the Linux/WSL
# build stays an empty stub.
[target.'cfg(target_os = "windows")'.dependencies]
windows = { workspace = true }

[dev-dependencies]
tokio = { workspace = true }
# tempfile is not a workspace dependency; 3.27 is already resolved in Cargo.lock.
Expand Down
28 changes: 28 additions & 0 deletions crates/openshell-driver-mxc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ default_configuration_id = "composable"
pc_least_privilege = false
pc_capabilities = []
debug = false
etw_audit = false
```

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:
Expand All @@ -58,6 +59,33 @@ Network policy support depends on the selected containment path. Policy
replacement and merge updates use the gateway's standard sandbox configuration
revision contract.

When `etw_audit` is enabled, each gateway process owns a distinct real-time ETW
session named from the stable `OpenShell-MXC-ETW` prefix, its process ID, and a
per-start discriminator. Starting another gateway never stops an existing
gateway's capture. Graceful shutdown stops the session by its owned handle. A
force-killed gateway can leave a stale session; the audit example removes only
matching sessions whose encoded owner process is no longer running.

The gateway-local OCSF JSONL sink is available only for the Windows/MXC path
and is opt-in. Set `OPENSHELL_OCSF_JSON=1` to enable it and optionally set
`OPENSHELL_OCSF_LOG_DIR` to override its `%PROGRAMDATA%\OpenShell\logs` default.
Other gateway deployments do not initialize this local file sink.

The ETW callback uses a non-blocking queue capped at 4,096 records and 16 MiB
of copied event data. Records that exceed either limit are dropped instead of
blocking the ETW pump or growing gateway memory. The gateway emits an immediate
warning identifying the audit coverage gap and rate-limits follow-up warnings
to once every 30 seconds while overload continues.

Audit attribution bootstraps only when the driver-owned `wxc-exec` PID and its
kernel process start key both match the values attached to the ETW record;
command text is never an ownership key. This generation key prevents a recycled
PID from inheriting the previous process's attribution regardless of delivery
delay. The process monitor retires the live PID at exit. Established identity,
activity, and correlation-vector links remain available for five seconds so
already in-flight ETW records can arrive, but retired PID evidence cannot resolve
them. Records without matching generation evidence remain unattributed.

## Prerequisites (live runs)

- Windows 11 Insider build ≥ 26300.8553
Expand Down
74 changes: 74 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,74 @@
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 / console
[1007] Process Activity - in-sandbox process launch (+ executable identity)
[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)
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.
-ShareDir <path> Host folder granted read-write to the workload. The script
derives a disposable policy and per-sandbox config for it.
-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 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.
- MXC process audit events record the executable basename only. Command-line
arguments are omitted from OCSF JSON and shorthand because they can contain
credentials, signed URLs, or PII.
30 changes: 30 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,30 @@
# 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, and etw_audit into a
# disposable copy of this file. Workload command and cwd are sandbox-scoped and
# passed separately through --driver-config-json.

[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"

Comment thread
araza008 marked this conversation as resolved.
debug = false

# Turn ON the Plane-A ETW -> OCSF audit consumer. This is the core of the example.
etw_audit = true
15 changes: 15 additions & 0 deletions crates/openshell-driver-mxc/examples/ocsf-audit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 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 workload folder read-write; everything
# else is default-deny. run-ocsf-audit.ps1 copies this policy into the result
# bundle and replaces the default grant with -ShareDir for that run.
version: 1

filesystem_policy:
include_workdir: false
read_only: []
read_write:
- "C:/work/openshell-mxc-demo"
Loading
Loading