Repository navigation
Refuse to delete through a path that no longer leads inside the scanned folder [patch] - #204
Merged
Merged
Conversation
…ed folder [patch] Deletion used the path string recorded at scan time. If a directory on that path was replaced by a symlink after the scan, for example during the "Proceed with deletion?" prompt, File.Delete followed it and removed an identical file outside the root the user approved, and the run reported it as an ordinary deletion. DeleteDuplicates now takes the scanned root. Immediately before each delete, the file's directory is resolved with every symlink and junction followed (RealPath) and must lie at or under the resolved root. Otherwise the file is skipped with a reason giving where its directory now leads. A root that is itself reached through a link still works, because both sides are resolved. Fixes #202 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017vfJW5MMN2e4Pk8UWLnvp9
…t [patch] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017vfJW5MMN2e4Pk8UWLnvp9
…t paths [patch] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017vfJW5MMN2e4Pk8UWLnvp9
…canned-root # Conflicts: # FileDeduplicator/Deduplicator.cs # README.md
|
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.



Deletion used the path string recorded at scan time. If a subdirectory was swapped for a symlink to an outside folder during the confirmation prompt,
File.Deletefollowed the link and deleted an identical file outside the scanned root.Changes
RealPathhelper. It resolves an absolute path by following every symlink and junction along it, for both relative and absolute targets and through nested links, with the same 40-link limit Linux uses.IsWithincompares paths case-insensitively on Windows and macOS, and treats a name that only shares the root's prefix (root-sibling) as outside it.Deduplicator.DeleteDuplicates(groups, root)now takes the scanned root. Immediately before each delete, the file's directory must resolve to the resolved root or somewhere under it. Otherwise the file is skipped with a reason that names where its directory now leads. If a path can't be resolved, the file is also skipped.Deduplicateverb passesoptions.Path, and test call sites passtree.Root.This takes the issue's first suggested fix, a resolve-and-contain check placed last, right before the delete. That shrinks the race window from the length of the prompt to microseconds but does not close it completely. A complete fix needs handle-relative
unlinkat, which would mean platform-specific deletion code, so it is left out of this PR.Tests
ASubdirectorySwappedForALinkOutsideTheRootIsNotDeletedThroughreproduces the issue. The outside file survives and is reported as skipped. The test fails with the check disabled and passes with it enabled.ARootReachedThroughALinkStillDeletesItsDuplicateschecks that a symlinked root isn't over-blocked.RealPathFollowsNestedRelativeLinkscovers the resolver and the prefix-sibling case.Note: #203 (for #201) also changes the
DeleteDuplicatessignature by adding an optionalafterDeleteparameter, so whichever PR merges second will need a one-line merge of the two parameters.Fixes #202
Generated by Claude Code