8000 Zip Slip via absolute-path entry names bypasses extraction path confinement (arbitrary file write) · Issue #1025 · zlib-ng/minizip-ng · GitHub
[go: up one dir, main page]

Skip to content

Zip Slip via absolute-path entry names bypasses extraction path confinement (arbitrary file write) #1025

Closed

Description

@cryptcrack

Summary

When extracting a ZIP archive without specifying an explicit destination directory (mz_zip_reader_save_all() called with destination_dir == NULL, which is exactly what the minizip -x CLI does by default, i.e., when -d is not specified), an archive entry whose name is an absolute path (e.g., /etc/cron.d/evil or /home/user/.ssh/authorized_keys) is written to that absolute path instead of being confined to the intended extraction directory.

This is a variant of the classic "Zip Slip" path traversal vulnerability. However, it does not rely on the usual relative ../../ traversal pattern. The existing path-sanitization logic in mz_path_resolve() already handles ./.. components and duplicate path separators correctly. Instead, the issue is that a leading path separator, which makes the entry name an absolute path, is neither stripped nor rejected, allowing a fully qualified path to pass through unchanged.

Root Cause

  1. mz_path_resolve() (mz_os.c) normalizes paths by removing . and .. segments, but fails to check or reject leading / separators. Absolute paths remain absolute.

  2. mz_zip_reader_save_all() (mz_zip_rw.c) does not prepends a destination directory when destination_dir is NULL (the default minizip -x behavior), leaving entry paths unaltered.

Impact: Without validation for leading slashes, archive entries with absolute paths are written directly to absolute system locations, enabling Zip Slip via absolute path traversal.

Reproduction

Craft a zip with one stored entry whose name field is an absolute path pointing outside an empty, dedicated extraction directory. Run minizip -x -o with that empty directory as the working directory, without -d. The payload lands at the literal absolute path instead of under the extraction directory, confirming the entry name isn't sanitized when no destination directory is given.

PoC file: evil.zip

Command:

$ ./minizip -x ./evil.zip 

Log

$ ./minizip -x ./evil.zip 
minizip-ng 4.2.2 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-x ./evil.zip 
Archive ./evil.zip
Extracting /tmp/pwn.txt
$ cat /tmp/pwn.txt 
hello
$ ./minizip -l ./evil.zip 
minizip-ng 4.2.2 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-l ./evil.zip 
      Packed     Unpacked Ratio Method   Attribs Date     Time  CRC-32     Name
      ------     -------- ----- ------   ------- ----     ----  ------     ----
           5            5  100% stored  81a40000 11-30-79 00:00 3610a686   /tmp/pwn.txt

Activity

  1. coderabbitai commented on Jul 23, 2026

    @coderabbitai
    🔗 Related PRs

    #985 - minizip: place erase temp on same filesystem when TMPDIR differs [closed]
    #1005 - fix: reject symlink targets that escape extraction dir [merged]
    #1014 - Allow recover flag to read zips with >65535 entries missing zip64 EOCD [merged]
    #1015 - Fix resource leaks [merged]
    #1022 - Harden extraction against destination symlink traversal [open]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. nmoinvaz commented on Jul 23, 2026

    @nmoinvaz
    Member

    This is expected behavior.

  3. cryptcrack commented on Jul 23, 2026

    @cryptcrack
    Author

    Thank you for your reply, @nmoinvaz

    Several archive extraction tools treat this behavior as a security issue rather than expected behavior. There are precedents such as CVE-2026-27117, where a similar absolute path extraction issue was addressed as a vulnerability and fixed.

    The concern is not path normalization itself, but that an archive entry can control an absolute filesystem path during the default extraction flow.

    A possible mitigation would be to reject absolute paths when destination_dir == NULL, while allowing users who explicitly need absolute path restoration to opt in via an explicit destination such as -d /.

    I leave the final decision on the desired behavior to the maintainers, but wanted to highlight that this pattern is commonly considered a security issue in archive extraction tools.

    Reference:
    GHSA-qvjh-hhw4-3gx9

  4. nmoinvaz commented on Jul 23, 2026

    @nmoinvaz
    Member

    Ok create a PR then.

  5. added 4 commits that reference this issue on Sep 4, 2026
    4b41a97
    ad4c9ae
    24113ce
    9695380
  6. added a commit that references this issue on Sep 5, 2026
    fcc8858
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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

      0