You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The old process container tests in /tests/scripts hadn't been updated since 0.6 and had numerous bugs.
This PR rebuilds the Windows process-container validation suite: splits the monolithic WinProcessContainer-Tests.ps1 into per-area scripts (like every other backend), adds the schema 0.8
directional networking coverage it never had, and removes the false greens that
let a mis-provisioned host report success having proven nothing.
Suite split.tests/scripts/WinProcessContainer-Tests.ps1 (1749 lines) is
replaced by run_processcontainer_all_tests.ps1 (probes the host once, writes
the resolved context to JSON, dispatches each area, merges results) plus 22 run_processcontainer_<area>_test.ps1 scripts that also run standalone. Shared
helpers live in tests/scripts/lib/WinProcessContainer.Common.ps1 (dot-sourced,
not imported: Initialize-WpcContext publishes the context into the caller's
scope) and WinProcessContainer.Native.ps1 (P/Invoke, dot-sourced only by the
three areas that need it). -Areas is aliased to the old -Phases, so existing
phase lists keep working.
Configs now emit 0.8.0-alpha with containment: processcontainer; they were
emitting 0.6 with an appcontainer value that is in no stable enum.
Legacy network fields pin the config to 0.7.0-alpha, and mixing them with a
directional key throws rather than silently emitting a 0.7 config carrying
0.8-only keys.
Schema 0.8 directional networking: the egress × ingress capability matrix,
model-3 equivalence, explicit egress rules, host loopback, the runtime proxy,
and the documented reject surface.
The legacy 0.7 network lane, kept as its own area so the compatibility path is
asserted separately from the directional one.
The UI policy resolution matrix, covering every documented value.
capabilities, captureDenials, lifecycle, and leastPrivilege rejection
and acceptance surfaces.
Path aliasing and most-specific-wins resolution.
Process plumbing: env, cwd, exit codes, timeout, and surviving children.
Bug Fixes / Changes
Removed false positives caused by the sandbox not launching
Expected tier is now properly enforced.
The dispatcher now stages the plm.exe and winhttp-proxy-shim.exe sidecars that wxc-exec
resolves next to its own image, without them the guarded-WPR captureDenials
fallback and the legacy proxy path fail as launch errors instead of policy
results
process-t1 now gets the same prepare-system-drive / prepare-null-device preparation as process-t3, since a T1 host still drives
the AppContainer fallback tiers.
wxc-ui-probe reported FAIL when user32.dll would not
load. Under ui.disable=true that is the expected outcome - the Win32k
syscall-disable mitigation takes the GUI subsystem with it - so FAIL claimed the
restriction was not enforced and would mask a real regression. Those cases now
report INCONCLUSIVE with a diagnostic.
Process-container configs and tests renamed with the processcontainer- prefix.
SBOX tests, fallbacks, and assertions removed.
🔗 References
No tracking issue.
docs/ci-validation-infrastructure.md — updated for the new entry point, the -RequireTier gate, and the process-t1 host-preparation change.
tests/scripts/README.md — updated for the per-area scripts, the
dot-sourcing requirement, and the T2 exclusion.
Contract under test: docs/process-container/networking.md and docs/sandbox-policy/0.8.0/networking/networking.md.
…alse greens
WinProcessContainer-Tests.ps1 had extensive negative networking coverage and
almost no positive coverage, and nothing exercised the schema 0.8 directional
network shape at all. Configs were still emitted at 0.6 with a containment
value (`appcontainer`) that is not in the stable enum at either 0.7 or 0.8.
Generator
- New-Config now emits 0.8.0-alpha with `containment: processcontainer`, and
gained cwd, capabilities, leastPrivilege and the directional network
parameters (egress/ingress defaults, hostLoopback, explicit egress rules,
runtime proxy, allowedProxyPeer).
- The legacy network fields stay on 0.7.0-alpha: supplying any of them pins
the version, and mixing them with a directional key now throws rather than
silently emitting a 0.7 config carrying 0.8-only keys.
New phases
- 8a capability matrix, 8b model-3 equivalence, 8c explicit egress rules,
8d host loopback, 8e runtime proxy, 8f the documented reject surface,
9 the legacy 0.7 lane incl. firewall rule teardown, 10 path aliasing,
11 process plumbing (env, cwd, exit codes, timeout, survivors).
Assertions encode the documented expectation from
docs/process-container/networking.md and the 0.8 policy spec, so some are
expected to fail against current behavior.
Tier gate
- The suite derives expectations from the tier the host selects, so it was
self-consistent anywhere -- and therefore silently useless on a host meant
to be T1 that fell back to T3. -RequireTier makes a mismatch a hard abort,
and the dispatcher passes base-container for process-t1 and
appcontainer-dacl for process-t3.
- process-t1 now gets the same host preparation as process-t3; without
prepare-system-drive the launch fails outright and no phase can report a
policy result.
False greens
Most negative assertions here are satisfied by a run in which the sandbox
never launched, so a mis-provisioned host reported green having proven
nothing. Guards added and applied throughout: Get-NetVerdict's NORUN state,
Test-VerdictsRan for differential assertions, an unconditional marker echo
with Test-WorkloadRan, and Test-WasRejected to separate a policy rejection
from a timeout or a launch failure. Phase 8f gained a positive control.
Two related bugs found while testing:
- wxc-exec echoes its redacted config to stderr and the log on every failure
path, so any assertion searching for a token was searching the harness's own
input. Remove-ConfigEcho excises the three echoed sections; it must cut them
out and keep the tail, since the echo is a prefix and all runner output
(tier selection, capability list) follows it.
- Invoke-Wxc waited for exit before draining the redirected pipes, so a child
that filled either buffer -- routine once a failure path dumps the whole
config -- was recorded as a hang, turning real rejections into timeouts.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The process-container harness had grown to 3,414 lines / 189 KB, twice the
size of the next largest script in the repo, and was the only Windows backend
suite still shipped as a single file. Reshape it into the layout the WSLc and
Seatbelt suites already use: an entry script that dispatches to per-area
scripts, over a shared library.
tests/scripts/run_processcontainer_all_tests.ps1 entry / dispatcher
tests/scripts/run_processcontainer_<area>_test.ps1 19 area scripts
tests/scripts/lib/WinProcessContainer.Common.ps1 shared helpers
tests/scripts/lib/WinProcessContainer.Native.ps1 P/Invoke shims
Each area script also runs standalone, which is the point: iterating on one
area no longer means driving the whole suite.
The library is dot-sourced rather than imported as a module, deliberately.
Initialize-WpcContext publishes the suite context into the *calling* script's
scope, which is what lets the ~63 helpers and all the phase bodies move
verbatim -- they read those names bare. As a module the same names would bind
to the module scope and every helper would silently read $null.
Areas report merged structured results rather than one pass/fail apiece: each
child writes a JSON document the entry merges, so per-assertion detail
survives. A child that dies before writing one is recorded as a failure
instead of vanishing from the summary, and MXC-FATAL (exit 78) still stops
the whole suite on the spot.
Verified behavior-preserving against the pre-split harness on the same host:
124 assertions both before and after, with the 63 failures an identical set.
The deltas reconcile exactly -- two removed T2 assertions that were passing,
two deliberate skips that are now recorded.
T2 (appcontainer-bfs) coverage is dropped; it is off by default behind the
tier2_bfs Cargo feature and is not in use. No phase exercised it, and all
four assertions were redundant with guards that remain: two duplicated
Assert-BfsSafety, and two re-ran the exact regex Assert-NoBfscfg had already
raised MXC-FATAL on two lines earlier, so they could only ever print PASS.
Assert-BfsSafety and Assert-NoBfscfg are kept as guards rather than tests --
invoking bfscfg.exe hard-locks the bfs.sys minifilter on 25H2. Also drops the
dead -AllowBfsTierSelection switch, which no caller ever passed.
Two fixes found while splitting:
- ValidateSet binds to the variable, not just to parameter binding, so it
re-fires when Initialize-WpcContext publishes context back into scope. An
unspecified -RequireTier threw. Area scripts drop the attribute and let
Initialize-WpcContext validate; the entry keeps it with '' in the set.
- Two areas both tagged their assertions P4c, making a failure in the merged
summary unattributable. The deny-ACE area is now P4d.
A deliberate skip is recorded as a skip rather than returning silently,
because an area that records nothing at all is otherwise indistinguishable
from one that did nothing due to a bug -- both the child and the entry treat
zero assertions as a failure.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tures
BaseContainer's "[ui subsystem]" telemetry comes from log_sandbox_spec(),
which decodes the legacy SBOX FlatBuffer and is called only under
`if !use_process_security_environment`. A run that takes the PSEC /
CreateProcessSecurityEnvironment path emits none of it, so the token greps
in Test-UiRestrictionsApplied / Test-Win32kMitigationApplied were unsound
in both directions there: positive assertions failed despite the
restriction holding, and the negated ones ("mitigation NOT applied")
passed vacuously.
Route all seven call sites through Record-UiTelemetryResult, which skips
when the log shows the PSEC spec being built. Detection is positive-proof,
so a run that dies before building any spec is still asserted and still
fails.
Also:
- Drop four orphaned tests/configs/network_*_test.json fixtures. They
varied only enforcementMode, which the NetworkLegacy07 area already
covers explicitly, and nothing referenced them.
- Re-derive child output color in the entry script. Console color is an
attribute rather than bytes, so it does not survive a pipe, and a child
killed mid-Write-Host left the console tinted for every later area.
- Prefix six process-container fixtures with processcontainer_ to match
the convention the other backends already follow.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds four areas -- capabilities, captureDenials, lifecycle/process, and
privilege/legacy-proxy -- and deepens the single-value cases in each. Suite
grows from 126 to 228 assertions.
processContainer.capabilities, captureDenials, learningMode, leastPrivilege,
lifecycle.*, process.inheritDefaultEnv, telemetry.enabled, the containment
intent alias, the supported schema-version range, and the three legacy 0.7
network.proxy shapes had no coverage at all. Four New-Config parameters were
declared but never passed by any area, which reads as coverage that does not
exist.
Hardens Test-WasRejected against three false-rejection classes it did not
catch: a post-tier-selection failure, a typed backend_error, and
runner_unavailable. Each of those is a host limitation rather than a policy
rejection, and counting them as rejections credited the policy under test for
the host being under-provisioned.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Follows the schema-reference correction: telemetry is 0.9.0-alpha+, so an
earlier version must reject it rather than ignore the request.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Validation.Infrastructure.Tests.yml is the only consumer of the 'enabled'
plan, so without it the process-container entries added to that plan have
nothing to schedule them. Retargets the push trigger from the SIP branch to
this one now that the branch is based on main.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Nineteen assertions failed for reasons in the fixtures rather than the
product:
- Capability names appear only in the legacy SBOX spec dump, so the five
assertions reading them are unobservable on a PSEC host. Gate them behind
Test-SpecDumpAvailable via a shared Record-CapabilityLogged helper.
- Host firewall rules are an AppContainer primitive, so enforcementMode
firewall/both and blockedHosts cannot enforce on a base-container host.
Gate on tier as well as elevation.
- process.env replaces the environment outright, so a block holding only the
variable under test cannot launch. Add Get-MinimalEnv.
- The selected-tier regex missed the word 'isolation'.
- UiIsolation is a closed wire enum, so an unrecognized value is rejected at
parse rather than defaulted; assert the rejection instead.
- BaseContainer needs no DACL augmentation for denied paths where the OS
supports them natively.
- Record the observed tail on the timeout and proxy assertions so a launch
failure is diagnosable from the log.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cuts comment lines from 2095 to 1677 across 26 files with no code changes.
Removes duplicated blocks, collapses the header boilerplate repeated in
every area script, and moves the shared parameter notes into
Initialize-WpcContext so they are written down once.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Test-WasRejected now requires positive evidence of a refusal (the Request
error banner or a typed config_parse/policy_validation code) and treats a
-1 exit as a launch failure, so an unexplained failure no longer counts as
a rejection. It also reads Stderr off the unwrapped result, which wrapped
Invoke-NetRun objects were bypassing.
Other fixes:
- the direct-egress proxy assertion now bypasses HTTP_PROXY, which curl was
otherwise honoring and reporting BLOCKED for free
- denied-path, ping, and Win32k phases require a start marker, since all
three were satisfied by a workload that never launched
- state-file checks compare against a baseline instead of deleting the
shared dacl-restore directory, which held other processes' records
- firewall rules are correlated by their embedded timestamp
- the valid-outputPath control requires the run not to be refused at all
- the empty-policy tier assertion is labelled as a repeatability check
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cuts:
- run_processcontainer_proxy_tests.ps1 was orphaned by the split; nothing
referenced it.
- UnitTests shelled cargo test, duplicating the CI Rust lane and requiring a
toolchain on a runner that deliberately tests a prebuilt artifact. It was
the only consumer of CargoLog.
- EmptyRelease and DeniedRelease re-ran two trivial checks against the release
binary; -SkipReleaseLane went with them.
- Assert-NoBfscfg and its ten call sites are gone. Assert-BfsSafety still
refuses to run against a tier2_bfs binary, which is the check that keeps the
suite from hanging a 25H2 host.
Each area used to declare a 17-parameter block so the entry script could
forward the resolved context, and every one of them repeated it. The entry
script now writes that context to a JSON file and passes -ContextJson; an
explicitly supplied parameter still wins, so standalone runs are unchanged.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pass
Move the legacy 0.7 network shape out of New-Config behind a -RawNetwork
escape hatch and a local New-LegacyConfig wrapper in the one area that uses
it, collapse the repeated per-file headers, and drop the separator rules.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Restore the legacy 0.7 proxy shapes, which the New-Config cleanup broke.
- Add LOCALAPPDATA to Get-MinimalEnv: Windows refuses to create a contained
process whose caller-supplied env lacks it, so three env tests never started.
- Share Get-SelectedTier, which tolerates the timestamps the logger writes
mid-line, so the containment-intent tiers compare non-empty values.
- Replace the timeout workload's ping, which dies instantly in the container,
with a cmd spin loop, and bound the elapsed time below as well as above --
a child that exits on its own was scoring two assertions green.
- Accept either documented timeout message.
- P8e now asserts the documented pair (runs, or is rejected cleanly) instead of
requiring a run, and skips the dependent egress check when nothing started.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… ran
wxc-ui-probe emitted FAIL -- which the harness scores as 'allowed' -- for the
seven user32-dependent tags whenever user32.dll would not load. That is exactly
what ui.disable=true causes, so the phase asserting that disable overrides every
permissive knob was reporting the mitigation working as the mitigation absent.
Those arms now emit INCONCLUSIVE, and the harness counts a missing GUI subsystem
under ui.disable=true as 'blocked', since it is strictly stronger than the
individual limit.
An INCONCLUSIVE nothing explains is now a failure, not a skip.
Also assert the documented floor once per run: with every UI knob permissive a
contained process should get every UI capability (UIPolicy_Schema.md:95,
os-version-support.md:185). It currently does not, and that stays red.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ng them
A build that supports JOB_OBJECT_UILIMIT_INJECTION and a probe that owned the
foreground leave no excuse for the injection limit not firing, so both sites
that recorded it as a warning now fail.
hostLoopback=allow that neither reaches the anchor nor produces a typed
rejection was recorded as a skip named 'rejected', which describes an outcome
that did not occur; it now fails.
Without SANDBOX_CAP_DENY_PATHS the enforcement test still cannot run, but the
documented refusal can be asserted, so that phase checks deniedPaths is refused
rather than skipping outright.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Several harness paths can still produce false results or omit intended coverage, including proxy functionality, empty capabilities, sidecar builds, and stderr validation.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Reorganizes Windows ProcessContainer validation into focused suites, expands schema 0.8 coverage, strengthens failure detection, and updates CI tier enforcement.
Changes:
Splits the monolithic suite into 22 independently runnable areas with shared helpers.
Adds networking, filesystem, UI, lifecycle, capability, and process-plumbing coverage.
Updates CI preparation, fixture names, documentation, and UI probe semantics.
This drops an explicitly supplied empty capability list, so the Caps = @() case in run_processcontainer_capabilities_test.ps1 actually tests an omitted processContainer.capabilities field. Preserve parameter presence so that case emits "capabilities": [] and exercises the intended contract.
if ($Capabilities.Count -gt 0) { $pc['capabilities'] = @($Capabilities) }
The overlapping deny must target the configured anchor's actual port too. With a non-443 ExternalAnchorUrl, this deny does not overlap the allow/request, so the precedence assertion no longer tests D4. tests/scripts/lib/WinProcessContainer.Common.ps1:1091
The loopback test must bypass proxy configuration explicitly. Otherwise an ambient curl/WinHTTP proxy can route this request away from 127.0.0.1, making the test report BLOCKED because of proxy behavior rather than hostLoopback enforcement.
Every case fetches the same public ExternalAnchorUrl, so these assertions only distinguish egress.default. In particular, allow/deny and allow/allow both succeed through internetClient even if ingress.default is ignored and privateNetworkClientServer is never granted. Add a private-network inbound or private-destination differential so the advertised ingress half of the capability matrix is exercised.
This equality compares only the three public-egress verdicts. Model 3 also promises denied inbound and denied host loopback, so an empty or omitted block could accidentally default either ingress control to allow and this would still pass. Exercise those controls for all three spellings before calling them equivalent.
Avoid false failure when sandbox blocks cmd.exe initialization
The launch marker is emitted by cmd.exe, but that wrapper is itself the mitigated sandbox process. This suite already notes that cmd.exe may fail to initialize under ui.disable=true, so a correctly enforced mitigation can prevent the marker and make $ranB false. Use positive runner evidence that CreateProcess succeeded, or have the probe emit and flush a pre-user32 marker while invoking it directly.
Fail unsupported User32 loading instead of silently skipping injection tests
src/testing/wxc_ui_probe/src/main.rs:264
This new INJECTION=INCONCLUSIVE path is treated by both PowerShell consumers as the known foreground-ownership race and therefore recorded as a skip. On ui.disable=false, failure to load user32.dll is not that race and should fail the test; otherwise a broken GUI/probe setup silently removes all injection coverage. Distinguish this reason in the two harnesses (or emit a distinct outcome) so only the documented foreground race is skipped.
Preserve ingress support capability and enforce expected proxy outcomes
This predicate collapses “BaseContainer/PSEC selected” and “PSEC 1.1 ingress is supported.” The probe already exposes baseContainerSupportsIngressHostLoopbackAllow, but it is dropped from $Script:Caps; consequently the loopback and identity-less proxy tests accept either success or clean rejection even on a host that advertises support, allowing a regression that rejects valid host-loopback policy to pass. Preserve that probe fact and require success when it is true, rejection when false.
The omitted-capabilities case emits no processContainer object at all, so
reading .processContainer threw under Set-StrictMode -Version Latest and
failed Phase 12b with an unhandled exception. Route both lookups through a
presence-checked helper, matching the PSObject.Properties guard convention
used elsewhere in the suite.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🟡 Changes recommended
Inconclusive injection handling can hide probe failures, the schema boundary test is stale, and a T3 network lane has an irrelevant reachability prerequisite.
Get a fresh assessment by requesting another Copilot review.
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
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 old process container tests in
/tests/scriptshadn't been updated since 0.6 and had numerous bugs.This PR rebuilds the Windows process-container validation suite: splits the monolithic
WinProcessContainer-Tests.ps1into per-area scripts (like every other backend), adds the schema 0.8directional networking coverage it never had, and removes the false greens that
let a mis-provisioned host report success having proven nothing.
Suite split.
tests/scripts/WinProcessContainer-Tests.ps1(1749 lines) isreplaced by
run_processcontainer_all_tests.ps1(probes the host once, writesthe resolved context to JSON, dispatches each area, merges results) plus 22
run_processcontainer_<area>_test.ps1scripts that also run standalone. Sharedhelpers live in
tests/scripts/lib/WinProcessContainer.Common.ps1(dot-sourced,not imported:
Initialize-WpcContextpublishes the context into the caller'sscope) and
WinProcessContainer.Native.ps1(P/Invoke, dot-sourced only by thethree areas that need it).
-Areasis aliased to the old-Phases, so existingphase lists keep working.
Probesrun_processcontainer_probes_test.ps1--probe(read-only)T3Forcedrun_processcontainer_filesystem_matrix_test.ps1T1DenyForcedrun_processcontainer_denied_paths_test.ps1FsEnumeraterun_processcontainer_filesystem_enumerate_test.ps1filesystem.enumeratePathsUiMitigationMatrixrun_processcontainer_ui_mitigations_test.ps1UiPolicyMatrixrun_processcontainer_ui_policy_matrix_test.ps1Capabilitiesrun_processcontainer_capabilities_test.ps1capabilitiesdocumented rejectionsCaptureDenialsrun_processcontainer_capture_denials_test.ps1captureDenials.outputPathvalidationLifecyclerun_processcontainer_lifecycle_test.ps1lifecycle.destroyOnExit/preservePolicyPrivilegerun_processcontainer_privilege_test.ps1leastPrivilege(LPAC)GlobalAtomIsolationrun_processcontainer_global_atom_test.ps1DaclDisabledrun_processcontainer_dacl_disabled_test.ps1allowDaclMutation=falserefusalCrashRecoveryrun_processcontainer_crash_recovery_test.ps1NetworkCapabilityMatrixrun_processcontainer_network_capability_test.ps1NetworkModel3Equivalencerun_processcontainer_network_model3_test.ps1NetworkEgressRulesrun_processcontainer_network_egress_test.ps1NetworkHostLoopbackrun_processcontainer_network_loopback_test.ps1NetworkProxyrun_processcontainer_network_proxy_test.ps1NetworkRejectionsrun_processcontainer_network_rejections_test.ps1NetworkLegacy07run_processcontainer_network_legacy07_test.ps1PathAliasingrun_processcontainer_path_aliasing_test.ps1ProcessPlumbingrun_processcontainer_process_plumbing_test.ps1New coverage.
0.8.0-alphawithcontainment: processcontainer; they wereemitting 0.6 with an
appcontainervalue that is in no stable enum.0.7.0-alpha, and mixing them with adirectional key throws rather than silently emitting a 0.7 config carrying
0.8-only keys.
model-3 equivalence, explicit egress rules, host loopback, the runtime proxy,
and the documented reject surface.
asserted separately from the directional one.
filesystem.enumeratePaths).capabilities,captureDenials,lifecycle, andleastPrivilegerejectionand acceptance surfaces.
Bug Fixes / Changes
plm.exeandwinhttp-proxy-shim.exesidecars thatwxc-execresolves next to its own image, without them the guarded-WPR captureDenials
fallback and the legacy proxy path fail as launch errors instead of policy
results
process-t1now gets the sameprepare-system-drive/prepare-null-devicepreparation asprocess-t3, since a T1 host still drivesthe AppContainer fallback tiers.
wxc-ui-probereported FAIL whenuser32.dllwould notload. Under
ui.disable=truethat is the expected outcome - the Win32ksyscall-disable mitigation takes the GUI subsystem with it - so FAIL claimed the
restriction was not enforced and would mask a real regression. Those cases now
report INCONCLUSIVE with a diagnostic.
processcontainer-prefix.🔗 References
No tracking issue.
docs/ci-validation-infrastructure.md— updated for the new entry point, the-RequireTiergate, and theprocess-t1host-preparation change.tests/scripts/README.md— updated for the per-area scripts, thedot-sourcing requirement, and the T2 exclusion.
docs/process-container/networking.mdanddocs/sandbox-policy/0.8.0/networking/networking.md.🔍 Validation
cargo test -p wxc_common -- config_parser— 406 passed, 0 failed (covers thecorpus divergence-inventory change).
✅ Checklist
Cargo.lock, thedependency-feed-checkcheck passes (see docs/pull-requests.md)📋 Issue Type