From ce81250a22da55b6b2fe250af315f5db8af73c188e3ff8d5a90168bce7297e5f Mon Sep 17 00:00:00 2001 From: nkrapp Date: Tue, 20 Jan 2026 12:25:08 +0100 Subject: [PATCH] Add CVE-2026-23949.patch to fix CVE-2026-23949 (bsc#1256954) --- CVE-2026-23949.patch | 122 ++++++++++++++++++++++++++++++++++ python-jaraco.context.changes | 5 ++ python-jaraco.context.spec | 2 + 3 files changed, 129 insertions(+) create mode 100644 CVE-2026-23949.patch diff --git a/CVE-2026-23949.patch b/CVE-2026-23949.patch new file mode 100644 index 0000000..e6d4393 --- /dev/null +++ b/CVE-2026-23949.patch @@ -0,0 +1,122 @@ +From f567f1be4c2cbcb43d54d9417d85c303abac28ca Mon Sep 17 00:00:00 2001 +From: "Jason R. Coombs" +Date: Mon, 12 Jan 2026 20:09:03 -0500 +Subject: [PATCH 1/9] Add repro as provided by tsigouris007 + +--- + tests/test_safety.py | 146 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 146 insertions(+) + create mode 100644 tests/test_safety.py + +Index: jaraco.context-5.3.0/tests/test_safety.py +=================================================================== +--- /dev/null ++++ jaraco.context-5.3.0/tests/test_safety.py +@@ -0,0 +1,72 @@ ++import io ++import sys ++import types ++from contextlib import nullcontext as does_not_raise ++ ++import pytest ++ ++import jaraco.context ++from jaraco.context import tarfile ++ ++ ++def make_tarball_with(member): ++ tar_data = io.BytesIO() ++ with tarfile.open(fileobj=tar_data, mode='w') as tar: ++ tarinfo = tarfile.TarInfo(name=member.path) ++ content = f'content for {member.path}' ++ bin_content = content.encode('ascii') ++ tarinfo.size = len(bin_content) ++ tar.addfile(tarinfo, io.BytesIO(bin_content)) ++ ++ tar_data.seek(0) ++ return tar_data ++ ++ ++cases = [ ++ types.SimpleNamespace( ++ path='dummy_dir/legitimate_file.txt', ++ expect=does_not_raise(), ++ ), ++ pytest.param( ++ types.SimpleNamespace( ++ path='dummy_dir/subdir/../legitimate_file.txt', ++ expect=does_not_raise(), ++ ), ++ marks=pytest.mark.skipif( ++ (3, 11) < sys.version_info < (3, 13), ++ reason='Fails with FileExistsError on Python 3.12', ++ ), ++ ), ++ types.SimpleNamespace( ++ path='dummy_dir/../../tmp/pwned_by_zipslip.txt', ++ expect=pytest.raises(tarfile.OutsideDestinationError), ++ ), ++ types.SimpleNamespace( ++ path='dummy_dir/../../../../home/pwned_home.txt', ++ expect=pytest.raises(tarfile.OutsideDestinationError), ++ ), ++ types.SimpleNamespace( ++ path='dummy_dir/../escaped.txt', ++ expect=pytest.raises(tarfile.OutsideDestinationError), ++ ), ++] ++ ++ ++@pytest.fixture(params=cases) ++def tarfile_case(request): ++ with tarfile.open(fileobj=make_tarball_with(request.param), mode='r') as tf: ++ yield types.SimpleNamespace( ++ tarfile=tf, ++ expect=request.param.expect, ++ ) ++ ++ ++def test_zipslip_exploit(tmp_path, tarfile_case): ++ """ ++ Ensure that protections from the default tarfile filter are applied. ++ """ ++ (member,) = tarfile_case.tarfile ++ with tarfile_case.expect: ++ tarfile_case.tarfile.extract( ++ member, path=tmp_path, filter=jaraco.context._default_filter ++ ) +Index: jaraco.context-5.3.0/jaraco/context.py +=================================================================== +--- jaraco.context-5.3.0.orig/jaraco/context.py ++++ jaraco.context-5.3.0/jaraco/context.py +@@ -62,12 +62,19 @@ def tarball( + try: + req = urllib.request.urlopen(url) + with tarfile.open(fileobj=req, mode='r|*') as tf: +- tf.extractall(path=target_dir, filter=strip_first_component) ++ tf.extractall(path=target_dir, filter=_default_filter) + yield target_dir + finally: + shutil.rmtree(target_dir) + + ++def _compose_tarfile_filters(*filters): ++ def compose_two(f1, f2): ++ return lambda member, path: f1(f2(member, path), path) ++ ++ return functools.reduce(compose_two, filters, lambda member, path: member) ++ ++ + def strip_first_component( + member: tarfile.TarInfo, + path, +@@ -76,6 +83,9 @@ def strip_first_component( + return member + + ++_default_filter = _compose_tarfile_filters(tarfile.data_filter, strip_first_component) ++ ++ + def _compose(*cmgrs): + """ + Compose any number of dependent context managers into a single one. diff --git a/python-jaraco.context.changes b/python-jaraco.context.changes index 1ce35c8..049521e 100644 --- a/python-jaraco.context.changes +++ b/python-jaraco.context.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue Jan 20 11:23:53 UTC 2026 - Nico Krapp + +- Add CVE-2026-23949.patch to fix CVE-2026-23949 (bsc#1256954) + ------------------------------------------------------------------- Tue Apr 1 15:34:31 UTC 2025 - Markéta Machová diff --git a/python-jaraco.context.spec b/python-jaraco.context.spec index 55da48a..2f2762b 100644 --- a/python-jaraco.context.spec +++ b/python-jaraco.context.spec @@ -24,6 +24,8 @@ Summary: Tools to work with functools License: MIT URL: https://github.com/jaraco/jaraco.context Source0: https://files.pythonhosted.org/packages/source/j/jaraco.context/jaraco.context-%{version}.tar.gz +# PATCH-FIX-UPSTREAM CVE-2026-23949.patch bsc#1256954 gh#jaraco/jaraco.context#7b26a42 +Patch0: CVE-2026-23949.patch BuildRequires: %{python_module backports.tarfile} BuildRequires: %{python_module pip} BuildRequires: %{python_module portend}