Skip to content

[Security] Zip/Rar/7z Archive Extraction Path Traversal (Incomplete CVE-2007-4559 Mitigation) #8052

Description

@spartan8806

Security Vulnerability Report

Reporter: Conner Webber (conner.webber000@gmail.com)
Severity: HIGH (CVSS 3.1: 8.2)
CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)

Summary

The ZipExtractor, RarExtractor, and SevenZipExtractor classes in datasets/utils/extract.py call extractall() without any path traversal validation on archive member filenames. This allows a malicious archive containing entries with directory traversal sequences (e.g., ../../../.bashrc) to write files outside the intended output directory.

Notably, the adjacent TarExtractor class in the same file already implements a safemembers() method (lines 87-120) that explicitly mitigates CVE-2007-4559 for tar archives by filtering out members with absolute paths or .. components. The zip, rar, and 7zip extractors were never given the same treatment.

Vulnerability Details

HIGH: ZipExtractor extractall() Without Path Traversal Validation

  • File: datasets/utils/extract.py:188
  • ZipExtractor.extract() calls zipfile.ZipFile.extractall() with zero path validation on member filenames
  • A malicious zip file in a dataset with entries like ../../../.bashrc writes outside the output directory
  • Exploitable when loading any dataset containing crafted zip archives via datasets.load_dataset()

MEDIUM: RarExtractor and SevenZipExtractor Same Issue

  • File: extract.py:206-214 (Rar), extract.py:251-252 (7zip)
  • Both call extractall() without member path validation
  • Same fix pattern needed as zip

Steps to Reproduce

  1. Create a malicious zip file with a path traversal entry:
import zipfile

with zipfile.ZipFile('malicious.zip', 'w') as zf:
    zf.writestr('../../../tmp/pwned.txt', 'arbitrary file write')
  1. Host as a dataset or place in a dataset's archive files
  2. Load the dataset with datasets.load_dataset() — the zip extractor writes pwned.txt to /tmp/ (or any traversed path) instead of the output directory

Impact

Arbitrary file write on the filesystem of any user who loads a dataset containing a crafted zip/rar/7z archive. This could lead to:

  • Overwriting configuration files (.bashrc, .profile, SSH keys)
  • Code execution via cron jobs, shell profiles, or Python path injection
  • Denial of service via overwriting critical files

This is especially dangerous because datasets is widely used (50M+ monthly downloads) and users routinely load untrusted community datasets from the Hugging Face Hub.

Suggested Fix

Apply the same safemembers() pattern already used for TarExtractor. For zip:

def _safemembers(zip_file, output_path):
    safe = []
    for member in zip_file.infolist():
        member_path = os.path.realpath(os.path.join(output_path, member.filename))
        if not member_path.startswith(os.path.realpath(output_path) + os.sep):
            logger.warning(f"Skipping {member.filename} — path traversal detected")
            continue
        safe.append(member)
    return safe

Then extract only safe members instead of calling extractall().

Affected Versions

All current versions of datasets (pip package) are believed to be affected.

References

  • CVE-2007-4559 — The original tar path traversal vulnerability that TarExtractor.safemembers() was built to mitigate
  • CWE-22 — Path Traversal
  • datasets/utils/extract.py lines 87-120 (existing tar mitigation) vs lines 188, 206-214, 251-252 (missing zip/rar/7z mitigation)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions