Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion autotest/test_zip.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pathlib import Path
from pprint import pprint
from shutil import which
from zipfile import ZipFile
from zipfile import ZipFile, ZipInfo

import pytest

Expand Down Expand Up @@ -74,3 +74,16 @@ def test_extractall_preserves_execute_permission(function_tmpdir, archive, mf):
path = function_tmpdir / exe_name
assert path.is_file()
assert os.access(path, os.X_OK) == mf


@excludes_platform("Windows")
def test_extract_strips_special_mode_bits(function_tmpdir):
zip_path = function_tmpdir / "setuid.zip"
info = ZipInfo("prog")
info.external_attr = 0o104755 << 16 # regular file, setuid + 0755
with ZipFile(zip_path, "w") as zf:
zf.writestr(info, b"#!/bin/sh\n")

out = function_tmpdir / "out"
MFZipFile(zip_path).extractall(out)
assert (out / "prog").stat().st_mode & 0o7777 == 0o755
3 changes: 2 additions & 1 deletion modflow_devtools/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@ def download_and_unzip(
file_path.unlink()
elif "tar" in file_path.suffix:
ar = tarfile.open(file_path)
ar.extractall(path=str(path))
# reject absolute paths, traversal, and links escaping the target dir
ar.extractall(path=str(path), filter="data")
ar.close()

# delete the zipfile
Expand Down
3 changes: 2 additions & 1 deletion modflow_devtools/zip.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def extract(self, member, path=None, pwd=None):
path = os.getcwd()

ret_val = self._extract_member(member, str(path), pwd)
attr = member.external_attr >> 16
# permission bits only, no setuid/setgid/sticky
attr = (member.external_attr >> 16) & 0o777
if attr != 0:
os.chmod(ret_val, attr)

Expand Down
Loading