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 <[email protected]> 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.
