Repository navigation
Fix unit_sandbox_ssrf leaf-swap flake on macOS CI - #367
Merged
Merged
Conversation
The TOCTOU test that swaps a regular decoy.txt for a symlink during read_from_workspace's re-check pause used an 80ms reader window and a 20ms planter sleep. On the loaded macos-arm64 runner, std::this_thread::sleep_for coarsely overshot, the planter swapped after the reader's O_NOFOLLOW open, and the reader saw the still-regular decoy -- CHECK_FALSE(ok) failed even though no host bytes leaked (the read returned the workspace bytes, not the secret). Widen the reader's pre-open window to 400ms and shrink the planter's pre-swap sleep to 5ms so the swap reliably lands after resolve_within_workspace and before the open, exercising the O_NOFOLLOW refusal path deterministically regardless of scheduler jitter or coarse macOS timer granularity. Verified locally on arm64: unit_sandbox_ssrf passes 8/8 runs.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
mainis red onmacos-arm64becauseunit_sandbox_ssrf(theO_NOFOLLOW refuses leaf symlink swap after resolvecase added in #316) fails on the loaded macOS runner. This blocks every open PR whose branch is based on currentmain(e.g. #342, and #338–#341 once they rebase ontomain).Root cause
The test races a planter thread (swap a regular
decoy.txtfor a symlink to a host file) againstread_from_workspace's re-check pause:resolve_within_workspace→ exists check →sleep(read_check_pause_ms = 80ms)→open(O_NOFOLLOW)sleep(20ms)→unlink→symlinkOn the
macos-arm64CI runner,std::this_thread::sleep_forhas coarse timer granularity and the box is heavily loaded (noteunit_sandbox_quotaalone takes ~373s there). The planter's 20ms sleep overshot past the reader's 80ms open, so the reader opened the still-regular decoy:ok = true, content was the workspace bytes (no secret leaked), butCHECK_FALSE(ok)failed.I confirmed
O_NOFOLLOWitself is fine on Darwin — a local probe showsopen(symlink, O_NOFOLLOW)returnsELOOP(errno 62). The failure is timing, not a portability bug.Fix
Widen the reader's pre-open window to 400ms and shrink the planter's pre-swap sleep to 5ms. The swap now reliably lands:
resolve_within_workspace(resolve is a handful of syscalls, ≪1ms, so a 5ms planter sleep guarantees resolve wins → the open hits theO_NOFOLLOWrefusal path rather than resolve-rejection), andO_NOFOLLOWopen (5ms ≪ 400ms, with huge margin against coarse macOS timer oversleep or scheduler jitter).Verified locally on arm64:
unit_sandbox_ssrfpasses 8/8 runs (was failing every run on the macOS CI runner).Scope
Test-only change (plus a CHANGELOG entry). No production code touched.
Made with Cursor