From f6ebf21df7b80bbb1e1e241ea12ee4bd24ef4083 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:51:25 +0000 Subject: [PATCH 1/2] Initial plan From fe810cf715dedec933f87c0dd8c4cf2300a6aabe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:54:19 +0000 Subject: [PATCH 2/2] Fix tarfile symlink/hardlink escape vulnerability in safe_extract Co-authored-by: rilma <14822065+rilma@users.noreply.github.com> --- pyiri2016/api/update.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pyiri2016/api/update.py b/pyiri2016/api/update.py index 2fd5adb..e97d28b 100644 --- a/pyiri2016/api/update.py +++ b/pyiri2016/api/update.py @@ -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)