Skip to content

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

@PuH4ck3rX

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

Metadata

Metadata

Labels

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

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions