Skip to content

fix(sevenz): normalize/reject embedded backslash in 7z entry names #376

Description

@bug-ops

Description

SafePath::validate does not normalize \ to / before path component analysis. The upstream sevenz_rust2::safe_join (removed when switching to ArchiveReader::for_each_entries in #375) did replace('\\', '/') prior to validation.

Impact

On Unix: an entry named ..\..\x is treated as one literal path component and extracted as a file with a backslash-containing name inside the destination directory. Not a security escape — the file lands inside dest — but the behavior silently changed from rejected (under the old safe_join) to accepted (under the current code).

On Windows: Path::components() splits on \, so traversal via ..\..\x is already caught by the .. check in SafePath::validate. No regression.

Reproduction Steps

  1. Create a 7z archive with an entry named ..\..\x
  2. Extract with allow_absolute_paths = false
  3. On Unix: extraction succeeds and writes dest/..\..\x (literal backslash name)
  4. Expected: rejection (PathTraversal or SecurityViolation)

Expected Behavior

Embedded \ in 7z entry names should be normalized to / before path validation, consistent with what safe_join did, and consistent with how Windows handles paths natively.

Actual Behavior

On Unix, ..\..\x is accepted and a file with a backslash-containing name is created inside the destination directory.

Environment

  • Version: 0.5.0
  • OS: Linux / macOS (Windows unaffected)
  • Archive format: 7z
  • Binding: all (core-level issue)

Proposed Fix

In the 7z adapter (formats/sevenz.rs), normalize entry names before constructing the PathBuf:

let entry_path = std::path::PathBuf::from(entry.name.replace('\\', "/"));

Add a unit test with a ..\..\x entry name verifying rejection on all platforms.

Notes

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions