You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by ju...@apache.org on 2024/07/12 15:12:55 UTC
(buildstream-plugins) 01/02: cargo.py: Check tar member paths
This is an automated email from the ASF dual-hosted git repository.
juergbi pushed a commit to branch juerg/tar
in repository https://gitbox.apache.org/repos/asf/buildstream-plugins.git
commit 4d7472abc8e21a3acddb04aeb4ae5a6ed48aa3eb
Author: Jürg Billeter <j...@bitron.ch>
AuthorDate: Fri Jul 12 17:11:46 2024 +0200
cargo.py: Check tar member paths
---
src/buildstream_plugins/sources/cargo.py | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/buildstream_plugins/sources/cargo.py b/src/buildstream_plugins/sources/cargo.py
index 6334a54..402b9ee 100644
--- a/src/buildstream_plugins/sources/cargo.py
+++ b/src/buildstream_plugins/sources/cargo.py
@@ -146,8 +146,14 @@ class Crate(SourceFetcher):
try:
mirror_file = self._get_mirror_file()
with tarfile.open(mirror_file) as tar:
- tar.extractall(path=directory)
members = tar.getmembers()
+ if hasattr(tarfile, "tar_filter"):
+ # Python 3.12+ (and older versions with backports)
+ tar.extractall(path=directory, filter="tar")
+ else:
+ for member in members:
+ self._assert_tarinfo_safe(member, directory)
+ tar.extractall(path=directory, members=members)
if members:
dirname = members[0].name.split("/")[0]
@@ -184,6 +190,30 @@ class Crate(SourceFetcher):
# Private helpers #
########################################################
+ # Assert that a tarfile is safe to extract; specifically, make
+ # sure that we don't do anything outside of the target
+ # directory (this is possible, if, say, someone engineered a
+ # tarfile to contain paths that start with ..).
+ def _assert_tarinfo_safe(self, member: tarfile.TarInfo, target_dir: str):
+ final_path = os.path.abspath(os.path.join(target_dir, member.path))
+ if not final_path.startswith(target_dir):
+ raise SourceError(
+ "{}: Tarfile attempts to extract outside the staging area: "
+ "{} -> {}".format(self, member.path, final_path)
+ )
+
+ if member.islnk():
+ linked_path = os.path.abspath(os.path.join(target_dir, member.linkname))
+ if not linked_path.startswith(target_dir):
+ raise SourceError(
+ "{}: Tarfile attempts to hardlink outside the staging area: "
+ "{} -> {}".format(self, member.path, final_path)
+ )
+
+ # Don't need to worry about symlinks because they're just
+ # files here and won't be able to do much harm once we are
+ # in a sandbox.
+
# _download()
#
# Downloads the crate from the url and caches it.