Skip to content

Bug: Unsafe Symlink detection code is overzealous #968

@pmqs

Description

@pmqs

This is a carveout from #943 to highlight the issue upfront.

The changes made for #936, which looks very like a fix for CVE-2025-11001, include use cases that are not unsafe.1

This issue arises when the directory tree used for running the unit tests includes a symbolic link, which is the case in my environment.

$ (cd build; ctest   --output-on-failure  -R '^raw.*generic'   -C Debug  )
Test project /home/pmqs/develop/minizip-ng/build
    Start 1: raw-zip-generic
1/7 Test #1: raw-zip-generic ..................   Passed    0.23 sec
    Start 2: raw-list-generic
2/7 Test #2: raw-list-generic .................   Passed    0.01 sec
    Start 3: raw-unzip-generic
3/7 Test #3: raw-unzip-generic ................***Failed    0.02 sec
minizip-ng 4.1.0 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-x -o -d /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip 
Archive /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip
Extracting empty.txt
Error -107 saving entries to disk /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip

    Start 4: raw-append-generic
4/7 Test #4: raw-append-generic ...............   Passed    0.02 sec
    Start 5: raw-append-unzip-generic
5/7 Test #5: raw-append-unzip-generic .........***Failed    0.02 sec
minizip-ng 4.1.0 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-x -o -d /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip 
Archive /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip
Extracting empty.txt
Error -107 saving entries to disk /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip

    Start 6: raw-erase-generic
6/7 Test #6: raw-erase-generic ................***Failed    0.08 sec
minizip-ng 4.1.0 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-o -e /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip test.c test.h 
Copying empty.txt
...
Copying single.txt
Error replacing archive with temp /tmp/mz_qw2Jnq

    Start 7: raw-erase-unzip-generic
7/7 Test #7: raw-erase-unzip-generic ..........***Failed    0.01 sec
minizip-ng 4.1.0 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-x -o -d /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip 
Archive /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip
Error -111 opening archive /home/pmqs/develop/minizip-ng/build/Testing/Temporary/raw-generic.zip


43% tests passed, 4 tests failed out of 7

Total Test time (real) =   0.50 sec

The following tests FAILED:
          3 - raw-unzip-generic (Failed)
          5 - raw-append-unzip-generic (Failed)
          6 - raw-erase-generic (Failed)
          7 - raw-erase-unzip-generic (Failed)
Errors while running CTest

My dev environment’s root directory is a symbolic link. This affects all zip extraction tests and leads to either a -111 or -107 error.

As the code stands it will not allow unzipping of files if there is already a pre-existing symlink in the target path. That has to be a bug.

Here is a way to reproduce the test failure

$ unzip -l /tmp/fred.zip 
Archive:  /tmp/fred.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     6926  2026-02-02 16:11   mz.h
---------                     -------
     6926                     1 file

$ mkdir /tmp/output

$ ln -s /tmp/output /tmp/linked

$  minizip -x -o -d /tmp/linked /tmp/fred.zip 
minizip-ng 4.1.0 - https://github.com/zlib-ng/minizip-ng
---------------------------------------------------
-x -d /tmp/linked /tmp/fred.zip 
Archive /tmp/fred.zip
Extracting mz.h
Error -107 saving entries to disk /tmp/fred.zip

This is me unzipping into a pre-existing directory tree that happens to include a symbolic link. That shouldn't trigger an error.

This is the same test with a very recent 7zip that includes the equivalent fix for unsafe symlinks. It works fine.

$ ~/install/bin/7z e -o/tmp/linked /tmp/fred.zip 

7-Zip (z) 26.00 (x64) : Copyright (c) 1999-2026 Igor Pavlov : 2026-02-12
 64-bit locale=C.UTF-8 Threads:8 OPEN_MAX:1048576, ASM

Scanning the drive for archives:
1 file, 2099 bytes (3 KiB)

Extracting archive: /tmp/fred.zip
--
Path = /tmp/fred.zip
Type = zip
Physical Size = 2099

Everything is Ok

Size:       6926
Compressed: 2099

$ ls /tmp/linked
mz.h

Possible Fix

This is me thinking out loud without checking what change for #943 actually does.

The code needs to keep track of all the symlink directories it has extracted and block any subsequent write operations within those directory structures. It shouldn't take account of the presence of pre-existing symlinks.

Symlinks with absolute paths feel like they should be straightforward(ish) to deal with. If the symlink is a relative path, it make things more complicated. Assume they need to be converted to absolute paths first.

Prior Art

The only prior art I can find is in the 7zip code. This is from the changelog

The code for handling symbolic links has been changed to provide greater security when extracting files from archives.

Footnotes

  1. See also https://github.com/pacbypass/CVE-2025-11001 for python code to create a zip file that triggers the issue

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