fix(scripts): widen the drive-root litter detector to known temp-sink names - #3489
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @kyle-sexton's task in 2m 36s —— View job Code review: PR #3489
SummaryReviewed the diff ( Correctness: I traced the new temp-sink loop (scripts/check-drive-root-litter.sh#L124-L146) by hand against each new test fixture (
The The single-letter loop is confirmed byte-identical to before except for one clarifying comment, as claimed in the PR description. The One maintainability finding posted inline: the new temp-sink loop duplicates the single-letter loop's candidate-build/containment-check/labeling logic almost verbatim. Not a bug, but the containment logic now lives in two places that must be kept in sync by hand — flagged as a non-blocking suggestion to extract a shared helper. See inline comment on Not independently verified (outside this lane's tool scope — no general Bash execution available, only No blocking issues found. |
|
Claude finished @kyle-sexton's task in 56s —— View job Security review
No security issues found. This PR touches
Per the skip gate (no security-relevant surface after reading the diff), no findings to report. |
|
Last security-reviewed head: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7afe36acf1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Claude has reviewed this PR 5 times. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
|
Claude finished @kyle-sexton's task in 3m 23s —— View job Code review: PR #3489 (re-review of
|
|
Claude finished @kyle-sexton's task in 1m 15s —— View job Security review: PR #3489
Applied the No security issues found. The commit makes the temp-sink class match case-insensitively (
This confirms the earlier "No security issues found" verdict from the first commit still holds for the full PR as it stands at |
|
Claude finished @kyle-sexton's task in 2m 29s —— View job Code review: PR #3489 (
|
|
Claude finished @kyle-sexton's task in 50s —— View job Security review: PR #3489 (delta since last-reviewed head
|
… names The detector scored an empty C:\tmp zero: its only class was a single-letter drive-root directory naming a mounted drive, and 'tmp' is not a single letter. Add a second class for known temp-sink names at a drive root, the residue of a POSIX /tmp literal handed to a Windows-native consumer. The vocabulary is the sibling guard's (block-windows-drive-tmp.sh): tmp is the only drive-root sink it blocks, so tmp is the only name here, and the two lists grow together. The single-letter class and its mounted-drive precision rationale are untouched. The new class carries the same cwd-containment guard plus a DRIVE_ROOT_LITTER_IGNORE_SINKS opt-out for an operator who keeps a deliberate C:\tmp. Still advisory per ADR 0003: no measured precision, no required gate. Exit codes and the reported non-Windows no-op (still evaluated first) are unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV
…idate guard Windows filesystems fold case, so C:\TMP is C:\tmp - but the sink matcher probed the literal lowercase name, which only worked where the host filesystem folded case for it, and the test fixtures' filesystems do not. Enumerate the drive root's entries and compare lowercased instead, so an uppercase TMP is caught on any host, and lowercase the DRIVE_ROOT_LITTER_IGNORE_SINKS values so an operator who writes TMP is not silently unexempted. Both directions are test-asserted. Also factor the copy-pasted candidate check (existence, cwd-containment, hit recording) into one record_if_litter helper called by both classes, so a future edit cannot land in one copy and miss the other. Single-letter class behavior is unchanged and its tests still pass; no-op ordering, exit codes, and the advisory posture are untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV
…e host gate
${var,,} is bash 4.0+ and macOS ships bash 3.2; the sink matcher is safe only
because the non-Windows gate exits before those lines are ever reached. Record
that ordering dependency where a future edit would otherwise move it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV
1812742 to
c798f0c
Compare
|
Claude finished @kyle-sexton's task in 1m 28s —— View job Code review: PR #3489 (
|
|
Claude finished @kyle-sexton's task in 1m 24s —— View job Security review: PR #3489 (
|
…r opt-out The suite exec'd the SUT without clearing DRIVE_ROOT_LITTER_IGNORE_SINKS - a documented, user-facing opt-out an operator may export persistently. Inherited into the ordinary-detection invocations it silently flips four sink assertions into false failures unrelated to the code under test, the silent-false-signal class f8ab565 closed elsewhere. run() and the two inline cwd invocations now set every env var the SUT reads explicitly (empty equals unset for both seams), the two opt-out tests keep setting a live value per-call, and the suite POISONS its own environment with DRIVE_ROOT_LITTER_IGNORE_SINKS=tmp up front so a future unhermetic invocation fails loudly in CI rather than only on an operator's machine. Verified by running the suite with the variable unset and with it exported: 26/26 both ways, identical assertion output. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV
|
Claude finished @kyle-sexton's task in 1m 17s —— View job Code review: PR #3489 (
|
|
Claude finished @kyle-sexton's task in 38s —— View job Security review: PR #3489 (
|
Closes #3495
Summary
scripts/check-drive-root-litter.shcould not see theC:\tmpresidue class — its only matcher was a single-letter drive-root directory naming a mounted drive, so the realC:\tmp\tmp.rSFIkHm5DOartifact observed on 2026-08-30 scored zero. This PR adds a second detection class for known temp-sink names at a drive root.Fix
C:\tmp) is reported as litter. Sink vocabulary is reused verbatim from the sibling guardplugins/guardrails/hooks/block-windows-drive-tmp.sh—tmpis the only drive-root sink that guard blocks (/var/tmpand%TEMP%are legitimate and never sit at a volume root), sotmpis the only name here; the two lists grow together. Matching is case-insensitive (Windows filesystems fold case, soC:\TMPisC:\tmp) via drive-root entry enumeration, so the contract holds on the case-sensitive filesystems the test fixtures run on.DRIVE_ROOT_LITTER_IGNORE_SINKS(space/comma-separated names, any casing) for an operator who deliberately keepsC:\tmp. An env var rather than a marker file inside the directory, because the detector cannot trust litter's own contents to prove intent. The opt-out is scoped to the sink class only; the single-letter class stays fully armed.record_if_litterhelper both classes call — the guard body moved verbatim); non-Windows no-op still evaluated first and printed; exit codes 0 clean / 1 litter / 2 usage unchanged; still advisory per ADR 0003 (no measured precision, no promotion to a required gate).docs/conventions/windows-path-emit/README.md§ "The detection net" (the SSOT) updated to describe both classes, case-insensitivity, and the opt-out.Verification
bash scripts/check-drive-root-litter.test.sh: 26/26 assertions pass — 15 pre-existing unchanged, plus new coverage: lowercase and uppercase (TMP) sink detected and named; non-sink drive-root directories not reported; opt-out works in both casings and both directions; opt-out does not bleed into the single-letter class; cwd-containment both directions for the sink class; both classes reported in one run.scripts/affected-tests.sh --run: selected the co-located suite, PASS; the doc change is covered byaffected-tests-no-suite.txt.hygienejob failure (shellcheck=failure, actionlint=failure) was infrastructure, not code: both steps failed downloading their tool binaries from GitHub releases (curl: (22) ... error: 502) before linting anything. The job passes on the current head.Related
C:\tmpresidue, which produced the command-time sibling guardblock-windows-drive-tmp.sh; this PR is the same concern pointed at the filesystem after a run.docs/adr/0003-verification-guards-earn-default-on-by-measured-precision.md— the doctrine keeping this detector advisory.docs/conventions/windows-path-emit/README.md— the owning convention.🤖 Generated with Claude Code
https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV