Skip to content

Fix extraction failure on Windows due to case-sensitive path comparison#988

Merged
adamhathcock merged 5 commits intomasterfrom
copilot/fix-file-write-error
Oct 28, 2025
Merged

Fix extraction failure on Windows due to case-sensitive path comparison#988
adamhathcock merged 5 commits intomasterfrom
copilot/fix-file-write-error

Conversation

Copy link
Contributor

Copilot AI commented Oct 28, 2025

Path.GetFullPath() on Windows can return paths with different casing than what's on disk (e.g., system32 vs System32 under LocalSystem account). The security check validating extraction paths was using case-sensitive comparison, causing false positives that blocked legitimate extractions.

Changes:

  • Add PathComparison property returning StringComparison.OrdinalIgnoreCase on Windows, StringComparison.Ordinal on Unix
  • Replace hardcoded StringComparison.Ordinal in 4 path validation checks (sync + async methods)
  • Use RuntimeInformation.IsOSPlatform(OSPlatform.Windows) for platform detection
  • Add tests validating both case-insensitive extraction and path traversal protection

Example:

// Before: Would throw on Windows LocalSystem when Path.GetFullPath casing differs
using var reader = archive.ExtractAllEntries();
reader.WriteAllToDirectory(
    "C:\\Windows\\system32\\config\\systemprofile\\AppData\\Local\\temp",
    new ExtractionOptions { ExtractFullPath = true }
);
// ExtractionException: Entry is trying to write a file outside of the destination directory

// After: Succeeds with platform-appropriate comparison

Path traversal security checks remain fully functional.

Original prompt

This section details on the original issue you should resolve

<issue_title>Entry is trying to write a file outside of the destination</issue_title>
<issue_description>I get the above mentioned error with this code

        using var reader = package.ExtractAllEntries();
        reader.WriteAllToDirectory(pkgWorkDir, new SharpCompress.Common.ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true, PreserveAttributes = true });

when running as Windows Service and the LocalSystem account. I use pkgWorkDir that is constructed starting with Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData).

On my system, this returns C:\Windows\system32\config\systemprofile\AppData\Local.
The code throws the error

Entry is trying to write a file outside of the destination directory: C:\Windows\system32\config\systemprofile\AppData\Local

As one can see, there is a difference between System32 and system32.

The lib code here uses StringComparison.Ordinal to compare the strings.

My issue could be fixed, if - under Windows OS - we use StringComparison.OrdinalIgnoreCase.

</issue_description>

Comments on the Issue (you are @copilot in this section)

@adamhathcock This isn't an obvious fix because other OSes use case sensitive file systems. I guess the addition of an option based on OS is relevant @adamhathcock or just write your own extraction code....the write to destination is just a shortcut method. @adamhathcock look and see what those methods do....they get the entries and stream copy basically @adamhathcock Odd...doing a search and the AI says the method will "normalize" casing but haven't found anywhere saying it yet

Image


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits October 28, 2025 10:16
- Add PathComparison property that uses OrdinalIgnoreCase on Windows and Ordinal on Unix
- Update all path comparison checks in ExtractionMethods to use PathComparison
- Add comprehensive tests for extraction with case-insensitive paths
- Ensure security check for path traversal still works correctly

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
…ection

- Replace Environment.OSVersion.Platform with RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
- Clarify test comment about platform-specific behavior
- Add using System.Runtime.InteropServices for RuntimeInformation

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix entry writing error for Windows Service in LocalSystem account Fix extraction failure on Windows due to case-sensitive path comparison Oct 28, 2025
Copilot AI requested a review from adamhathcock October 28, 2025 10:24
@adamhathcock adamhathcock marked this pull request as ready for review October 28, 2025 11:13
@adamhathcock
Copy link
Owner

@copilot format this code

Copy link
Contributor Author

Copilot AI commented Oct 28, 2025

@copilot format this code

The code has been formatted with CSharpier. All 432 files pass the formatting check with no issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Entry is trying to write a file outside of the destination

2 participants

Comments