Skip to content

Commit a01095d

Browse files
committed
minor bug fixed.
1 parent 2c9d2c4 commit a01095d

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

pmultiqc/modules/common/file_utils.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,25 @@ def extract_zip(file_path: str, extract_to: str) -> None:
5353
max_size = 10 * 1024 * 1024 * 1024 # 10GB limit
5454

5555
with zipfile.ZipFile(file_path, "r") as zip_ref:
56+
# Get absolute path of extract_to for proper comparison
57+
extract_to_abs = os.path.abspath(extract_to)
58+
5659
# Security: Check for path traversal in zip entries
5760
for member in zip_ref.namelist():
58-
# Normalize the path and check for path traversal attempts
59-
member_path = os.path.normpath(os.path.join(extract_to, member))
60-
if not member_path.startswith(os.path.abspath(extract_to)):
61-
raise ValueError(f"Attempted path traversal in zip file: {member}")
61+
# Check for explicit path traversal attempts first
6262
if ".." in member or member.startswith("/"):
6363
raise ValueError(f"Invalid path in zip file: {member}")
6464

65+
# Normalize the member path (remove leading slashes and normalize)
66+
member_normalized = os.path.normpath(member.lstrip("/"))
67+
68+
# Join with extract_to and normalize to get the full path
69+
member_path = os.path.normpath(os.path.join(extract_to_abs, member_normalized))
70+
71+
# Check if the resolved path is within extract_to directory
72+
if not member_path.startswith(extract_to_abs + os.sep) and member_path != extract_to_abs:
73+
raise ValueError(f"Attempted path traversal in zip file: {member}")
74+
6575
# Security: Check for zip bombs
6676
total_uncompressed_size = sum(info.file_size for info in zip_ref.infolist())
6777
compression_ratio = total_uncompressed_size / file_size if file_size > 0 else 0
@@ -83,15 +93,25 @@ def extract_gz(file_path: str, extract_to: str) -> None:
8393
def extract_tar(file_path: str, extract_to: str) -> None:
8494
"""Extract a tar file with security checks against path traversal."""
8595
with tarfile.open(file_path, "r:*") as tar_ref:
96+
# Get absolute path of extract_to for proper comparison
97+
extract_to_abs = os.path.abspath(extract_to)
98+
8699
# Security: Check for path traversal in tar entries
87100
for member in tar_ref.getmembers():
88-
# Normalize the path and check for path traversal attempts
89-
member_path = os.path.normpath(os.path.join(extract_to, member.name))
90-
if not member_path.startswith(os.path.abspath(extract_to)):
91-
raise ValueError(f"Attempted path traversal in tar file: {member.name}")
101+
# Check for explicit path traversal attempts first
92102
if ".." in member.name or member.name.startswith("/"):
93103
raise ValueError(f"Invalid path in tar file: {member.name}")
94104

105+
# Normalize the member path (remove leading slashes and normalize)
106+
member_normalized = os.path.normpath(member.name.lstrip("/"))
107+
108+
# Join with extract_to and normalize to get the full path
109+
member_path = os.path.normpath(os.path.join(extract_to_abs, member_normalized))
110+
111+
# Check if the resolved path is within extract_to directory
112+
if not member_path.startswith(extract_to_abs + os.sep) and member_path != extract_to_abs:
113+
raise ValueError(f"Attempted path traversal in tar file: {member.name}")
114+
95115
tar_ref.extractall(extract_to)
96116
log.info(f"Extracted {file_path} to {extract_to}")
97117

0 commit comments

Comments
 (0)