Skip to content
Merged
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: 13 additions & 2 deletions pyiri2016/api/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,25 @@ def is_within_directory(base_dir, target):
except ValueError:
return False

def safe_extract(tar, path=".", members=None, *, numeric_owner=False):
def safe_extract(tar, path=".", *, numeric_owner=False):

# Use the built-in extraction filter when available (Python >=3.11.4 / >=3.12)
if hasattr(tarfile, "data_filter"):
tar.extractall(path, numeric_owner=numeric_owner, filter=tarfile.data_filter)
return

safe_members = []
for member in tar.getmembers():
# Reject symlinks, hardlinks and special files to prevent
# escape-via-link attacks even when the path looks safe.
if member.issym() or member.islnk() or member.isdev():
raise ValueError(f"Unsafe tar member type: {member.name}")
member_path = os.path.join(path, member.name)
if not is_within_directory(path, member_path):
raise ValueError("Attempted Path Traversal in Tar File")
safe_members.append(member)

tar.extractall(path, members, numeric_owner=numeric_owner)
tar.extractall(path, safe_members, numeric_owner=numeric_owner)

safe_extract(tar, path=directory)
os.remove(retrieved_fullpath)