From 40b6b17733f0dbbb1e8782f129a5043c0c47223e Mon Sep 17 00:00:00 2001 From: changtao Date: Mon, 17 Feb 2025 15:42:05 +0800 Subject: [PATCH] fix CVE-2025-27516 (cherry picked from commit 05727cf4e9a4ca756361d4a3e10e38d70710d093) --- backport-CVE-2025-27516.patch | 105 ++++++++++++++++++++++++++++++++++ python-jinja2.spec | 9 ++- 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2025-27516.patch diff --git a/backport-CVE-2025-27516.patch b/backport-CVE-2025-27516.patch new file mode 100644 index 0000000..edac71b --- /dev/null +++ b/backport-CVE-2025-27516.patch @@ -0,0 +1,105 @@ +From 065334d1ee5b7210e1a0a93c37238c86858f2af7 Mon Sep 17 00:00:00 2001 +From: David Lord +Date: Wed, 5 Mar 2025 10:08:48 -0800 +Subject: [PATCH] attr filter uses env.getattr +--- + Jinja2-3.0.3/CHANGES.rst | 3 +++ + Jinja2-3.0.3/src/jinja2/filters.py | 38 ++++++++++++----------------- + Jinja2-3.0.3/tests/test_security.py | 11 +++++++++ + 3 files changed, 30 insertions(+), 22 deletions(-) + +diff --git a/Jinja2-3.0.3/CHANGES.rst b/Jinja2-3.0.3/CHANGES.rst +index 55d8a96..9170467 100644 +--- a/Jinja2-3.0.3/CHANGES.rst ++++ b/Jinja2-3.0.3/CHANGES.rst +@@ -1,5 +1,8 @@ + .. currentmodule:: jinja2 + ++- The ``|attr`` filter does not bypass the environment's attribute lookup, ++ allowing the sandbox to apply its checks. :ghsa:`cpwx-vrp4-4pq7` ++ + - Escape template name before formatting it into error messages, to avoid + issues with names that contain f-string syntax. + :issue:`1792`, :ghsa:`gmj6-6f8f-6699` +diff --git a/Jinja2-3.0.3/src/jinja2/filters.py b/Jinja2-3.0.3/src/jinja2/filters.py +index f3d4fca..0449901 100644 +--- a/Jinja2-3.0.3/src/jinja2/filters.py ++++ b/Jinja2-3.0.3/src/jinja2/filters.py +@@ -6,6 +6,7 @@ import typing + import typing as t + import warnings + from collections import abc ++from inspect import getattr_static + from itertools import chain + from itertools import groupby + +@@ -1382,32 +1383,25 @@ def do_reverse(value: t.Union[str, t.Iterable[V]]) -> t.Union[str, t.Iterable[V] + def do_attr( + environment: "Environment", obj: t.Any, name: str + ) -> t.Union[Undefined, t.Any]: +- """Get an attribute of an object. ``foo|attr("bar")`` works like +- ``foo.bar`` just that always an attribute is returned and items are not +- looked up. ++ """Get an attribute of an object. ``foo|attr("bar")`` works like ++ ``foo.bar``, but returns undefined instead of falling back to ``foo["bar"]`` ++ if the attribute doesn't exist. + + See :ref:`Notes on subscriptions ` for more details. + """ ++ # Environment.getattr will fall back to obj[name] if obj.name doesn't exist. ++ # But we want to call env.getattr to get behavior such as sandboxing. ++ # Determine if the attr exists first, so we know the fallback won't trigger. + try: +- name = str(name) +- except UnicodeError: +- pass +- else: +- try: +- value = getattr(obj, name) +- except AttributeError: +- pass +- else: +- if environment.sandboxed: +- environment = t.cast("SandboxedEnvironment", environment) +- +- if not environment.is_safe_attribute(obj, name, value): +- return environment.unsafe_undefined(obj, name) +- +- return value +- +- return environment.undefined(obj=obj, name=name) +- ++ # This avoids executing properties/descriptors, but misses __getattr__ ++ # and __getattribute__ dynamic attrs. ++ getattr_static(obj, name) ++ except AttributeError: ++ # This finds dynamic attrs, and we know it's not a descriptor at this point. ++ if not hasattr(obj, name): ++ return environment.undefined(obj=obj, name=name) ++ ++ return environment.getattr(obj, name) + + @typing.overload + def sync_do_map( +diff --git a/Jinja2-3.0.3/tests/test_security.py b/Jinja2-3.0.3/tests/test_security.py +index 9c8bad6..323c6b5 100644 +--- a/Jinja2-3.0.3/tests/test_security.py ++++ b/Jinja2-3.0.3/tests/test_security.py +@@ -189,3 +189,14 @@ class TestStringFormatMap: + + with pytest.raises(SecurityError): + t.render() ++ ++ ++ def test_attr_filter(self) -> None: ++ env = SandboxedEnvironment() ++ t = env.from_string( ++ """{{ "{0.__call__.__builtins__[__import__]}" ++ | attr("format")(not_here) }}""" ++ ) ++ ++ with pytest.raises(SecurityError): ++ t.render() +-- +2.46.0 + diff --git a/python-jinja2.spec b/python-jinja2.spec index 18d9a0b..970aa87 100644 --- a/python-jinja2.spec +++ b/python-jinja2.spec @@ -2,7 +2,7 @@ Name: python-jinja2 Version: 3.0.3 -Release: 6 +Release: 7 Summary: A full-featured template engine for Python License: BSD URL: http://jinja.pocoo.org/ @@ -12,6 +12,7 @@ Patch6000: backport-CVE-2024-22195.patch Patch6001: backport-CVE-2024-34064.patch Patch6002: backport-CVE-2024-56326.patch Patch6003: backport-CVE-2024-56201.patch +Patch6004: backport-CVE-2025-27516.patch BuildArch: noarch @@ -67,6 +68,12 @@ popd %doc Jinja2-%{version}/examples %changelog +* Mon Mar 10 2025 changtao - 3.0.3-7 +- Type:CVE +- CVE:CVE-2025-27516 +- SUG:NA +- DESC:fix CVE-2025-27516 + * Thu Dec 26 2024 weihaohao - 3.0.3-6 - Type:CVE - CVE:CVE-2024-56201 -- Gitee