From a9ee1895376a2d188fc102955e37d1831476ea19 Mon Sep 17 00:00:00 2001 From: zhangxianting Date: Tue, 2 Jul 2024 21:50:04 +0800 Subject: [PATCH] Fix CVE-2024-5569 --- backport-CVE-2024-5569.patch | 110 +++++++++++++++++++++++++++++++++++ python-zipp.spec | 8 ++- 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 backport-CVE-2024-5569.patch diff --git a/backport-CVE-2024-5569.patch b/backport-CVE-2024-5569.patch new file mode 100644 index 0000000..e2fc422 --- /dev/null +++ b/backport-CVE-2024-5569.patch @@ -0,0 +1,110 @@ +From fd604bd34f0343472521a36da1fbd22e793e14fd Mon Sep 17 00:00:00 2001 +From: "Jason R. Coombs" +Date: Fri, 31 May 2024 12:31:40 -0400 +Subject: [PATCH] Merge pull request #120 from jaraco/bugfix/119-malformed-paths + + Sanitize malformed paths + +--- + tests/test_path.py | 18 +++++++++++ + zipp/__init__.py | 58 +++++++++++++++++++++++++++++++++++- + 2 files changed, 75 insertions(+), 1 deletion(-) + +diff --git a/tests/test_path.py b/tests/test_path.py +index 03fd2aa..53664d4 100644 +--- a/tests/test_path.py ++++ b/tests/test_path.py +@@ -574,3 +574,21 @@ class TestPath(unittest.TestCase): + zipp.Path(alpharep) + with self.assertRaises(KeyError): + alpharep.getinfo('does-not-exist') ++ ++ @__import__('pytest').mark.skip(reason="infinite loop") ++ def test_malformed_paths(self): ++ """ ++ Path should handle malformed paths. ++ """ ++ data = io.BytesIO() ++ zf = zipfile.ZipFile(data, "w") ++ zf.writestr("/one-slash.txt", b"content") ++ zf.writestr("//two-slash.txt", b"content") ++ zf.writestr("../parent.txt", b"content") ++ zf.filename = '' ++ root = zipfile.Path(zf) ++ assert list(map(str, root.iterdir())) == [ ++ 'one-slash.txt', ++ 'two-slash.txt', ++ 'parent.txt', ++ ] +diff --git a/zipp/__init__.py b/zipp/__init__.py +index 6d05d9a..f78c272 100644 +--- a/zipp/__init__.py ++++ b/zipp/__init__.py +@@ -85,7 +85,63 @@ class InitializedState: + super().__init__(*args, **kwargs) + + +-class CompleteDirs(InitializedState, zipfile.ZipFile): ++class SanitizedNames: ++ """ ++ ZipFile mix-in to ensure names are sanitized. ++ """ ++ ++ def namelist(self): ++ return list(map(self._sanitize, super().namelist())) ++ ++ @staticmethod ++ def _sanitize(name): ++ r""" ++ Ensure a relative path with posix separators and no dot names. ++ Modeled after ++ https://github.com/python/cpython/blob/bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c/Lib/zipfile/__init__.py#L1799-L1813 ++ but provides consistent cross-platform behavior. ++ >>> san = SanitizedNames._sanitize ++ >>> san('/foo/bar') ++ 'foo/bar' ++ >>> san('//foo.txt') ++ 'foo.txt' ++ >>> san('foo/.././bar.txt') ++ 'foo/bar.txt' ++ >>> san('foo../.bar.txt') ++ 'foo../.bar.txt' ++ >>> san('\\foo\\bar.txt') ++ 'foo/bar.txt' ++ >>> san('D:\\foo.txt') ++ 'D/foo.txt' ++ >>> san('\\\\server\\share\\file.txt') ++ 'server/share/file.txt' ++ >>> san('\\\\?\\GLOBALROOT\\Volume3') ++ '?/GLOBALROOT/Volume3' ++ >>> san('\\\\.\\PhysicalDrive1\\root') ++ 'PhysicalDrive1/root' ++ >>> san('abc/') ++ 'abc/' ++ >>> san('../..') ++ Traceback (most recent call last): ++ ... ++ ValueError: Empty filename ++ """ ++ ++ def allowed(part): ++ return part and part not in {'..', '.'} ++ ++ # Remove the drive letter. ++ # Don't use ntpath.splitdrive, because that also strips UNC paths ++ bare = re.sub('^([A-Z]):', r'\1', name, flags=re.IGNORECASE) ++ clean = bare.replace('\\', '/') ++ parts = clean.split('/') ++ joined = '/'.join(filter(allowed, parts)) ++ if not joined: ++ raise ValueError("Empty filename") ++ return joined + '/' * name.endswith('/') ++ ++ ++class CompleteDirs(InitializedState, SanitizedNames, zipfile.ZipFile): + """ + A ZipFile subclass that ensures that implied directories + are always included in the namelist. +-- +2.43.0 + diff --git a/python-zipp.spec b/python-zipp.spec index 43218f3..0241bfb 100644 --- a/python-zipp.spec +++ b/python-zipp.spec @@ -1,11 +1,12 @@ %global _empty_manifest_terminate_build 0 Name: python-zipp Version: 3.18.1 -Release: 1 +Release: 2 Summary: Backport of pathlib-compatible object wrapper for zip files License: MIT URL: https://github.com/jaraco/zipp Source0: https://pypi.io/packages/source/z/zipp/zipp-%{version}.tar.gz +Patch3000: backport-CVE-2024-5569.patch BuildArch: noarch %description @@ -35,7 +36,7 @@ Provides: python3-zipp-doc A pathlib-compatible Zipfile object wrapper. A backport of the Path object. %prep -%autosetup -n zipp-%{version} +%autosetup -n zipp-%{version} -p1 # Skip tests that depend on jaraco.itertools sed -i "/import jaraco.itertools/d" tests/test_path.py @@ -65,6 +66,9 @@ pytest -k "not test_joinpath_constant_time" %{_docdir}/* %changelog +* Tue Jul 09 2024 zhangxianting - 3.18.1-2 +- Fix CVE-2024-5569 + * Sat May 11 2024 wangxiaomeng - 3.18.1-1 - Upgrade version to 3.18.1 - Bypass ZipFile.namelist in glob for better performance. (#106) -- Gitee