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
{{ message }}
Repository navigation
--output that is a symlink to the --input folder passes validation and overwrites the source icons (exit 0) #157
Arguments.Validate rejects an --output that is the --input directory. That guard was added for #120 so the masks cannot replace the source icons. But IsSameDirectory (IconHelper/Arguments.cs:95-99) compares the two paths as strings only, using Path.TrimEndingDirectorySeparator and string.Equals with PathComparison. TryResolveDirectory resolves paths with Path.GetFullPath, which does not follow links. So any second spelling of the same directory gets past the check. That covers a symlink, a junction, a bind mount, and on Windows an 8.3 short name.
When that happens, ProcessDirectory writes <base name>.png into the output folder, which is the input folder. The source icons are overwritten in place, and the run prints Done. N file(s) written. and exits 0.
iconhelper -i icons -o icons is correctly rejected with "--output must not be the --input directory". The symlinked spelling of the same folder is not.
Suggested fix
When the output directory already exists, compare directory identity instead of path text. Two ways to do that:
Resolve both paths to their final targets, for example with Directory.ResolveLinkTarget(path, returnFinalTarget: true) on each segment, or with realpath semantics.
Compare the file-system identity of the two directories: device and inode on Unix, volume serial and file ID on Windows.
A non-existent --output cannot alias anything yet, so it can keep the string comparison.
Acceptance criteria
Validate fails with the existing "--output must not be the --input directory" error when --output is a symlink to --input.
It also fails the other way round, when --input is a symlink to --output.
A regression test in ArgumentsTests creates a directory symlink to pin this. It is Inconclusive where symlinks can't be created.
Priority: High. The source artwork is overwritten in place with no warning, and the run exits 0. It only happens when --output is a second spelling of --input (a symlink, junction, bind mount or 8.3 name), but the damage can't be undone unless the icons are under version control.
Area: CLI argument validation: IconHelper/Arguments.cs, in IsSameDirectory and TryResolveDirectory.
Activity
matt-edmondson commentedon Oct 30, 2026
Triage
--outputis a second spelling of--input(a symlink, junction, bind mount or 8.3 name), but the damage can't be undone unless the icons are under version control.IconHelper/Arguments.cs, inIsSameDirectoryandTryResolveDirectory.AbsoluteFilePathrejects), and The.new.pngskip silently drops real inputs and doesn't protect reruns, because outputs are never named.new.png#149, about rerun protection with.new.png.Generated by Claude Code