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
Closes gaps in the backend validation suites where a behaviour was claimed but never actually exercised. No product code changes — this is tests, fixtures, and one shared helper.
Seatbelt (macOS)
deniedPaths is now probed for what it actually denies: writes, directory listing, delete, rename, and metadata reads.
A denied subtree nested under a readwritePaths grant is checked for AF_UNIX bind() and connect(). A socket under a broad read-write root is a control plane (Docker, ssh-agent, gpg-agent), so reaching one would be an escape. The listener runs on the host because the sandbox is the client here.
An aliased deniedPaths entry (deny written as /tmp/…, grants written as /private/tmp/…) is checked to still outrank both a read-only and a read-write grant — the deny only outranks if alias resolution ran first.
WSLc
The isolated/bridged egress pair is now a real oracle. Both fixtures run the same raw-IP TCP connect, so "reached" vs "blocked" reflects the posture rather than DNS or a missing interpreter. The previous isolated fixture used wget against a hostname, which reports the same thing whether egress is blocked or the image simply lacks wget.
Per-destination egress rules (allow and deny) are now asserted to be rejected. WSLc networking is all-or-nothing — no CAP_NET_ADMIN for in-container rules — so a rule must be refused, not quietly widened to the posture default.
A proxy URL carrying credentials is asserted to be rejected: process.env without inheritDefaultEnv launches through env -i NAME=VALUE, which puts the URL in argv and therefore in /proc/<pid>/cmdline.
IsolationSession
New "Lifecycle G" group in the state-aware suite covering what a live session does rather than just its request/response shape: that the mandated all-allow network posture really carries traffic, that exec output reaches the caller mid-run, that process.timeout ends a command and leaves the session usable, that a caller killed mid-exec doesn't take the sandbox with it, that repeating a lifecycle call doesn't corrupt the sandbox, and that the agent account named in provision metadata is created and removed.
New tests/scripts/lib/LoopbackAnchor.ps1 gives the network assertions a positive oracle — a host loopback listener an isolated session can reach — so they cover the session's posture instead of the runner's outbound internet access.
Known failures
The new coverage found two real bugs, so this cannot go green as-is. Both are filed and neither is caused by this PR:
A second deprovision on the same sandboxId is documented to report
stale_id, and start/stop/exec all do. deprovision does not: RemoveUser
reports success for an agent user that is already gone, so the runner
never sees the ERROR_NOT_FOUND it would promote.
MXC's side is already correct -- deprovision_agent_user classifies with
StalePromotion::Eligible -- and synthesizing the error here would
manufacture the provenance that classify_api_failure explicitly forbids.
So record the gap rather than asserting it, and let #1429 track the fix.
Assert-KnownGap never fails the suite, and reports when the expectation
starts holding so the waiver leaves with the fix.
Refs #1429
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The process is checked only before reading the file. If buffered output is flushed while the process exits between that check and Read-LiveFile, this returns true even though the marker was never observed during execution; that can falsely pass the streaming test and make the caller-kill test target an already-exited process. Recheck HasExited after observing the marker.
Prevent post-exit output from satisfying incremental delivery
This can mark $sawEarly after the process has exited: output may flush between the loop's HasExited check and the file read. In that race, an implementation that buffers everything until exit passes the incremental-delivery oracle. Recheck the process after reading the marker.
Updated curl commands to include --noproxy option for better handling of requests.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
The only timing check is < 45s for a configured 3s timeout, so an implementation that ignores this value and applies a 30–40s timeout still passes; without a lower bound, an immediate unrelated termination after the first echo can also pass. Bound the observation around the requested deadline with reasonable CI tolerance so this test actually verifies process.timeout, rather than merely proving the 59s command did not finish naturally.
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
Closes gaps in the backend validation suites where a behaviour was claimed but never actually exercised. No product code changes — this is tests, fixtures, and one shared helper.
Seatbelt (macOS)
deniedPathsis now probed for what it actually denies: writes, directory listing, delete, rename, and metadata reads.readwritePathsgrant is checked for AF_UNIXbind()andconnect(). A socket under a broad read-write root is a control plane (Docker,ssh-agent,gpg-agent), so reaching one would be an escape. The listener runs on the host because the sandbox is the client here.deniedPathsentry (deny written as/tmp/…, grants written as/private/tmp/…) is checked to still outrank both a read-only and a read-write grant — the deny only outranks if alias resolution ran first.WSLc
wgetagainst a hostname, which reports the same thing whether egress is blocked or the image simply lackswget.CAP_NET_ADMINfor in-container rules — so a rule must be refused, not quietly widened to the posture default.process.envwithoutinheritDefaultEnvlaunches throughenv -i NAME=VALUE, which puts the URL in argv and therefore in/proc/<pid>/cmdline.IsolationSession
process.timeoutends a command and leaves the session usable, that a caller killed mid-exec doesn't take the sandbox with it, that repeating a lifecycle call doesn't corrupt the sandbox, and that the agent account named in provision metadata is created and removed.tests/scripts/lib/LoopbackAnchor.ps1gives the network assertions a positive oracle — a host loopback listener an isolated session can reach — so they cover the session's posture instead of the runner's outbound internet access.Known failures
The new coverage found two real bugs, so this cannot go green as-is. Both are filed and neither is caused by this PR:
stat()succeeds on adeniedPathsentry (fails on all three macOS runners).deprovisionreports success instead ofstale_id(fails on all four isolation-session runners). This is most likely an OS-level issue. Marked as "KNOWN GAP" in test suite.🔗 References
Surfaced by the new coverage in this PR (not fixed by it):
stale_idstat()succeeds on adeniedPathsentry, leaking size and timestamps🔍 Validation
Scheduled Validation Tests, nightly plan: 36 of 39 jobs passed. Every failure is accounted for above.
✅ Checklist
Cargo.lock, thedependency-feed-checkcheck passes (see docs/pull-requests.md)📋 Issue Type
Microsoft Reviewers: Open in CodeFlow