diff --git a/SOURCES/CVE-2024-56326.patch b/SOURCES/CVE-2024-56326.patch new file mode 100644 index 0000000..7cfa7ca --- /dev/null +++ b/SOURCES/CVE-2024-56326.patch @@ -0,0 +1,151 @@ +From 2df1f7886e9e87face85569d5794ba690932c382 Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Wed, 22 Jan 2025 12:37:29 +0100 +Subject: [PATCH] CVE-2024-56326 + +--- + Jinja2-2.10.1/jinja2/sandbox.py | 65 +++++++++++++++------------- + Jinja2-2.10.1/tests/test_security.py | 17 ++++++++ + 2 files changed, 53 insertions(+), 29 deletions(-) + +diff --git a/Jinja2-2.10.1/jinja2/sandbox.py b/Jinja2-2.10.1/jinja2/sandbox.py +index 752e812..5516f96 100644 +--- a/Jinja2-2.10.1/jinja2/sandbox.py ++++ b/Jinja2-2.10.1/jinja2/sandbox.py +@@ -15,6 +15,7 @@ + import types + import operator + from collections import Mapping ++from functools import update_wrapper + from jinja2.environment import Environment + from jinja2.exceptions import SecurityError + from jinja2._compat import string_types, PY2 +@@ -134,16 +135,6 @@ class _MagicFormatMapping(Mapping): + return len(self._kwargs) + + +-def inspect_format_method(callable): +- if not isinstance(callable, (types.MethodType, +- types.BuiltinMethodType)) or \ +- callable.__name__ not in ('format', 'format_map'): +- return None +- obj = callable.__self__ +- if isinstance(obj, string_types): +- return obj +- +- + def safe_range(*args): + """A range that can't generate ranges with a length of more than + MAX_RANGE items. +@@ -372,6 +363,9 @@ class SandboxedEnvironment(Environment): + except AttributeError: + pass + else: ++ fmt = self.wrap_str_format(value) ++ if fmt is not None: ++ return fmt + if self.is_safe_attribute(obj, argument, value): + return value + return self.unsafe_undefined(obj, argument) +@@ -389,6 +383,9 @@ class SandboxedEnvironment(Environment): + except (TypeError, LookupError): + pass + else: ++ fmt = self.wrap_str_format(value) ++ if fmt is not None: ++ return fmt + if self.is_safe_attribute(obj, attribute, value): + return value + return self.unsafe_undefined(obj, attribute) +@@ -402,34 +399,44 @@ class SandboxedEnvironment(Environment): + obj.__class__.__name__ + ), name=attribute, obj=obj, exc=SecurityError) + +- def format_string(self, s, args, kwargs, format_func=None): +- """If a format call is detected, then this is routed through this +- method so that our safety sandbox can be used for it. ++ def wrap_str_format(self, value): ++ """If the given value is a ``str.format`` or ``str.format_map`` method, ++ return a new function than handles sandboxing. This is done at access ++ rather than in :meth:`call`, so that calls made without ``call`` are ++ also sandboxed. + """ +- if isinstance(s, Markup): +- formatter = SandboxedEscapeFormatter(self, s.escape) ++ if not isinstance( ++ value, (types.MethodType, types.BuiltinMethodType) ++ ) or value.__name__ not in ("format", "format_map"): ++ return None ++ f_self = value.__self__ ++ if not isinstance(f_self, str): ++ return None ++ str_type = type(f_self) ++ is_format_map = value.__name__ == "format_map" ++ if isinstance(f_self, Markup): ++ formatter = SandboxedEscapeFormatter(self, escape=f_self.escape) + else: + formatter = SandboxedFormatter(self) + +- if format_func is not None and format_func.__name__ == 'format_map': +- if len(args) != 1 or kwargs: +- raise TypeError( +- 'format_map() takes exactly one argument %d given' +- % (len(args) + (kwargs is not None)) +- ) ++ vformat = formatter.vformat ++ def wrapper(*args, **kwargs): ++ if is_format_map: ++ if kwargs: ++ raise TypeError("format_map() takes no keyword arguments") ++ if len(args) != 1: ++ raise TypeError( ++ f"format_map() takes exactly one argument ({len(args)} given)" ++ ) ++ kwargs = args[0] ++ args = () + +- kwargs = args[0] +- args = None ++ return str_type(vformat(f_self, args, kwargs)) + +- kwargs = _MagicFormatMapping(args, kwargs) +- rv = formatter.vformat(s, args, kwargs) +- return type(s)(rv) ++ return update_wrapper(wrapper, value) + + def call(__self, __context, __obj, *args, **kwargs): + """Call an object from sandboxed code.""" +- fmt = inspect_format_method(__obj) +- if fmt is not None: +- return __self.format_string(fmt, args, kwargs, __obj) + + # the double prefixes are to avoid double keyword argument + # errors when proxying the call. +diff --git a/Jinja2-2.10.1/tests/test_security.py b/Jinja2-2.10.1/tests/test_security.py +index 5c8639c..1719644 100644 +--- a/Jinja2-2.10.1/tests/test_security.py ++++ b/Jinja2-2.10.1/tests/test_security.py +@@ -206,3 +206,20 @@ class TestStringFormatMap(object): + env = SandboxedEnvironment() + t = env.from_string('{{ ("a{x.foo}b{y}"|safe).format_map({"x":{"foo": 42}, "y":""}) }}') + assert t.render() == 'a42b<foo>' ++ ++ def test_indirect_call(self): ++ def run(value, arg): ++ return value.run(arg) ++ ++ env = SandboxedEnvironment() ++ env.filters["run"] = run ++ t = env.from_string( ++ """{% set ++ ns = namespace(run="{0.__call__.__builtins__[__import__]}".format) ++ %} ++ {{ ns | run(not_here) }} ++ """ ++ ) ++ ++ with pytest.raises(SecurityError): ++ t.render() +-- +2.48.0 + diff --git a/SPECS/python-jinja2.spec b/SPECS/python-jinja2.spec index 6077ee7..4d6f13f 100644 --- a/SPECS/python-jinja2.spec +++ b/SPECS/python-jinja2.spec @@ -27,7 +27,7 @@ Name: python-jinja2 Version: 2.10.1 -Release: 5%{?dist} +Release: 6%{?dist} Summary: General purpose template engine Group: Development/Languages License: BSD @@ -48,6 +48,12 @@ Patch1: CVE-2024-22195.patch # Resolved upstream: https://github.com/pallets/jinja/commit/0668239dc6b44ef38e7a6c9f91f312fd4ca581cb Patch2: CVE-2024-34064.patch +# Security fix for CVE-2024-56326 +# Resolved upstream: https://github.com/pallets/jinja/commit/91a972f5808973cd441f4dc06873b2f8378f30c7 +# Tracking bug: https://bugzilla.redhat.com/show_bug.cgi?id=2333856 +# Patch backported from upstream without changelog and typing. +Patch3: CVE-2024-56326.patch + BuildArch: noarch %description @@ -126,6 +132,7 @@ environments. %patch0 -p1 %patch1 -p1 %patch2 -p1 +%patch3 -p1 # cleanup @@ -228,6 +235,10 @@ popd %changelog +* Wed Jan 22 2025 Lumír Balhar - 2.10.1-6 +- Security fix for CVE-2024-56326 +Resolves: RHEL-74677 + * Tue May 07 2024 Lumír Balhar - 2.10.1-5 - Security fix for CVE-2024-34064 Resolves: RHEL-35651