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
_engine_gate_relevant's marker-free fallback calls os.path.samefile on every whitespace token of everyBash/PowerShell command in every session. Its own docstring says it scans separator-carrying words; the implementation applies no such filter. This is both a doc/code mismatch and the identified source of the unbounded stall that #1423 investigated and that PR #3523 works around rather than fixes.
Evidence
plugins/disk-hygiene/skills/clean/scripts/destructive_guard.py, marker-free branch of _engine_gate_relevant:
Every candidate reaches _same_file_as_bundled, which calls os.path.samefile(word, bundled) and, for relative words, a second samefile against the engine's own directory. So an ordinary git log --oneline --graph --decorate origin/main performs a filesystem identity check on each of its words.
The function's docstring describes something narrower:
A path-like word (containing a separator) that is the SAME FILE as the bundled engine — a symlink or hard link under any name — gates regardless of its filename.
and the branch's own inline comment says:
scan their whitespace tokens for separator-carrying words and identity-check those
Neither the whitespace-token path nor the _literal_shell_words path filters on a separator.
Why it matters
The module docstring already names this as the strongest candidate for the one observed 17-second hang:
the strongest identified candidate for the 17s itself is _engine_gate_relevant's marker-free fallback, which calls os.path.samefile on every separator-containing word of every Bash/PowerShell command in every session
Note that sentence says "every separator-containing word", which is what the code was believed to do. It scans every word.
The latency is unbounded, not merely large: samefile on a dead drive letter, a disconnected UNC path, or a stale network mount blocks for as long as the OS takes to fail. No deadline value fixes that — it is why PR #3523 changed the watchdog's expiry action instead of tuning its timeout. The stall itself is still here.
Two distinct costs:
Latency, paid by every shell tool call in every session, proportional to token count.
Reach. A guard that only governs disk-hygiene engine invocations performs filesystem calls against arbitrary user-supplied path tokens from entirely unrelated commands.
Suggested fix
Filter the marker-free candidate set to separator-carrying words, which is what both the docstring and the inline comment already describe.
This is a semantics change to the security core and should not ride along in a performance PR. It needs its own review of the residual set, because it narrows what the gate sees. The relevant question for a reviewer: the function's contract already lists
a PATH-installed alias with no separator, an alias inside a command the literal parser rejects when the marker is absent, and a copied engine
as accepted residuals of the copy-evasion class. A separator filter appears to add nothing beyond the first of those, which is already accepted — but that needs confirming, not assuming, and the marker-carrying branches must stay untouched.
Explicit cases for a hard-linked engine under a non-marker name, invoked with and without a separator, since that is the class the filter could narrow. Note os.link cannot cross volumes on Windows; a cross-volume failure silently degrades such a test into a copy test, which exercises a different, already-accepted residual and reports no gap.
A measurement of samefile calls per invocation, before and after, on a representative command.
Summary
_engine_gate_relevant's marker-free fallback callsos.path.samefileon every whitespace token of everyBash/PowerShellcommand in every session. Its own docstring says it scans separator-carrying words; the implementation applies no such filter. This is both a doc/code mismatch and the identified source of the unbounded stall that #1423 investigated and that PR #3523 works around rather than fixes.Evidence
plugins/disk-hygiene/skills/clean/scripts/destructive_guard.py, marker-free branch of_engine_gate_relevant:Every candidate reaches
_same_file_as_bundled, which callsos.path.samefile(word, bundled)and, for relative words, a secondsamefileagainst the engine's own directory. So an ordinarygit log --oneline --graph --decorate origin/mainperforms a filesystem identity check on each of its words.The function's docstring describes something narrower:
and the branch's own inline comment says:
Neither the whitespace-token path nor the
_literal_shell_wordspath filters on a separator.Why it matters
The module docstring already names this as the strongest candidate for the one observed 17-second hang:
Note that sentence says "every separator-containing word", which is what the code was believed to do. It scans every word.
The latency is unbounded, not merely large:
samefileon a dead drive letter, a disconnected UNC path, or a stale network mount blocks for as long as the OS takes to fail. No deadline value fixes that — it is why PR #3523 changed the watchdog's expiry action instead of tuning its timeout. The stall itself is still here.Two distinct costs:
Suggested fix
Filter the marker-free candidate set to separator-carrying words, which is what both the docstring and the inline comment already describe.
This is a semantics change to the security core and should not ride along in a performance PR. It needs its own review of the residual set, because it narrows what the gate sees. The relevant question for a reviewer: the function's contract already lists
as accepted residuals of the copy-evasion class. A separator filter appears to add nothing beyond the first of those, which is already accepted — but that needs confirming, not assuming, and the marker-carrying branches must stay untouched.
Verification expected of a fix
os.linkcannot cross volumes on Windows; a cross-volume failure silently degrades such a test into a copy test, which exercises a different, already-accepted residual and reports no gap.samefilecalls per invocation, before and after, on a representative command.Related
_carries_markercompares basenames rather than substrings.