Skip to content

shutil.unpack_archive() on Windows writes outside extract_dir for ZIP entries with drive-prefixed names #146581

Description

@PuH4ck3rX

Bug report

Bug description:

Summary

I found a Windows-specific issue in shutil.unpack_archive() when extracting ZIP files.

In Lib/shutil.py, the private helper _unpack_zipfile() skips names that start with / or contain .., but it does not reject or sanitize Windows drive-prefixed names such as D:/path/file.

On Windows, such names are joined into a drive-qualified path and can escape the intended extraction directory. As a result, a crafted ZIP archive can cause files to be written outside extract_dir.

Affected component

  • Lib/shutil.py
  • _unpack_zipfile()

Impact

A crafted ZIP archive can cause an arbitrary file write outside extract_dir on Windows.

Trigger condition

  • Platform: Windows
  • Archive format: ZIP
  • A ZIP entry name contains a drive prefix such as D:/...
  • extract_dir is on a different drive

Tested environment

I reproduced this on Windows with Python 3.12.8.

Minimal reproduction

I attached a minimal repro script:

  • repro_shutil_unpack_zip_windows_drive_path_min.py

The repro creates a ZIP archive containing an entry like:

D:/shutil_outside_min.txt

and then calls:

shutil.unpack_archive(str(zip_path), str(extract_dir))
With extract_dir on another drive, the file is written outside the intended extraction directory.

Root cause
The validation in _unpack_zipfile() appears incomplete for Windows path semantics. Checking only for leading / and .. is not sufficient, because drive-prefixed paths such as D:/... are still treated as rooted or drive-qualified paths by Windows path handling.

For comparison, zipfile's own extraction logic strips drive information before extraction, but shutil._unpack_zipfile() does not.

Expected behavior
ZIP entries that are absolute, drive-prefixed, or otherwise resolve outside extract_dir on Windows should be rejected or normalized so that extraction always remains within extract_dir.

Actual behavior
A crafted ZIP entry with a drive prefix can escape extract_dir and be written to another location.

Additional context
I previously reported this privately to the Python Security Response Team on March 28, 2026, but I have not received a response yet, so I am opening this issue for tracking and triage.

I also attached a short write-up:

vuln_shutil_unpack_archive_zip_windows_drive_path.md

shutil_unpack_archive_zip_windows_drive_path_min.zip

CPython versions tested on:

CPython main branch, 3.14

Operating systems tested on:

Windows

Linked PRs

Activity

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

Metadata

Metadata

Labels

3.10only security fixes3.11only security fixes3.12only security fixes3.13bugs and security fixes3.14bugs and security fixes3.15pre-release feature fixes, bugs and security fixesOS-windowsstdlibStandard Library Python modules in the Lib/ directorytype-securityA security issue

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions