forked from microsoft/azurelinux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[AUTO-CHERRYPICK] python-jinja2 : addresss CVE-2024-22195, CVE-2024-3…
…4064, CVE-2024-56201, CVE-2024-56326 - branch 3.0-dev (microsoft#11868) Co-authored-by: Kanishk Bansal <[email protected]>
- Loading branch information
1 parent
d8f78a8
commit 39fefe3
Showing
7 changed files
with
312 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
From 3bfb481d9e1c469387ecc7717c4c5cba411d8c79 Mon Sep 17 00:00:00 2001 | ||
From: Kanishk-Bansal <[email protected]> | ||
Date: Thu, 2 Jan 2025 06:52:42 +0000 | ||
Subject: [PATCH] Fix CVE-2024-22195 | ||
|
||
--- | ||
src/jinja2/filters.py | 28 +++++++++++++++++++++------- | ||
tests/test_filters.py | 6 ++++++ | ||
2 files changed, 27 insertions(+), 7 deletions(-) | ||
|
||
diff --git a/src/jinja2/filters.py b/src/jinja2/filters.py | ||
index ed07c4c..c7ecc9b 100644 | ||
--- a/src/jinja2/filters.py | ||
+++ b/src/jinja2/filters.py | ||
@@ -248,13 +248,17 @@ def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K | ||
yield from value.items() | ||
|
||
|
||
+_space_re = re.compile(r"\s", flags=re.ASCII) | ||
+ | ||
+ | ||
@pass_eval_context | ||
def do_xmlattr( | ||
eval_ctx: "EvalContext", d: t.Mapping[str, t.Any], autospace: bool = True | ||
) -> str: | ||
"""Create an SGML/XML attribute string based on the items in a dict. | ||
- All values that are neither `none` nor `undefined` are automatically | ||
- escaped: | ||
+ | ||
+ If any key contains a space, this fails with a ``ValueError``. Values that | ||
+ are neither ``none`` nor ``undefined`` are automatically escaped. | ||
|
||
.. sourcecode:: html+jinja | ||
|
||
@@ -273,12 +277,22 @@ def do_xmlattr( | ||
|
||
As you can see it automatically prepends a space in front of the item | ||
if the filter returned something unless the second parameter is false. | ||
+ | ||
+ .. versionchanged:: 3.1.3 | ||
+ Keys with spaces are not allowed. | ||
""" | ||
- rv = " ".join( | ||
- f'{escape(key)}="{escape(value)}"' | ||
- for key, value in d.items() | ||
- if value is not None and not isinstance(value, Undefined) | ||
- ) | ||
+ items = [] | ||
+ | ||
+ for key, value in d.items(): | ||
+ if value is None or isinstance(value, Undefined): | ||
+ continue | ||
+ | ||
+ if _space_re.search(key) is not None: | ||
+ raise ValueError(f"Spaces are not allowed in attributes: '{key}'") | ||
+ | ||
+ items.append(f'{escape(key)}="{escape(value)}"') | ||
+ | ||
+ rv = " ".join(items) | ||
|
||
if autospace and rv: | ||
rv = " " + rv | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
From 71ac6eb2bb8ff62f7b70ca21b1d33fc59f01396d Mon Sep 17 00:00:00 2001 | ||
From: Kanishk-Bansal <[email protected]> | ||
Date: Thu, 2 Jan 2025 13:53:49 +0000 | ||
Subject: [PATCH] Fix CVE-2024-34064 | ||
|
||
--- | ||
src/jinja2/filters.py | 22 +++++++++++++++++----- | ||
1 file changed, 17 insertions(+), 5 deletions(-) | ||
|
||
diff --git a/src/jinja2/filters.py b/src/jinja2/filters.py | ||
index c7ecc9b..bdf6f22 100644 | ||
--- a/src/jinja2/filters.py | ||
+++ b/src/jinja2/filters.py | ||
@@ -248,7 +248,9 @@ def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K | ||
yield from value.items() | ||
|
||
|
||
-_space_re = re.compile(r"\s", flags=re.ASCII) | ||
+# Check for characters that would move the parser state from key to value. | ||
+# https://html.spec.whatwg.org/#attribute-name-state | ||
+_attr_key_re = re.compile(r"[\s/>=]", flags=re.ASCII) | ||
|
||
|
||
@pass_eval_context | ||
@@ -257,8 +259,14 @@ def do_xmlattr( | ||
) -> str: | ||
"""Create an SGML/XML attribute string based on the items in a dict. | ||
|
||
- If any key contains a space, this fails with a ``ValueError``. Values that | ||
- are neither ``none`` nor ``undefined`` are automatically escaped. | ||
+ **Values** that are neither ``none`` nor ``undefined`` are automatically | ||
+ escaped, safely allowing untrusted user input. | ||
+ | ||
+ User input should not be used as **keys** to this filter. If any key | ||
+ contains a space, ``/`` solidus, ``>`` greater-than sign, or ``=`` equals | ||
+ sign, this fails with a ``ValueError``. Regardless of this, user input | ||
+ should never be used as keys to this filter, or must be separately validated | ||
+ first. | ||
|
||
.. sourcecode:: html+jinja | ||
|
||
@@ -278,6 +286,10 @@ def do_xmlattr( | ||
As you can see it automatically prepends a space in front of the item | ||
if the filter returned something unless the second parameter is false. | ||
|
||
+ .. versionchanged:: 3.1.4 | ||
+ Keys with ``/`` solidus, ``>`` greater-than sign, or ``=`` equals sign | ||
+ are not allowed. | ||
+ | ||
.. versionchanged:: 3.1.3 | ||
Keys with spaces are not allowed. | ||
""" | ||
@@ -287,8 +299,8 @@ def do_xmlattr( | ||
if value is None or isinstance(value, Undefined): | ||
continue | ||
|
||
- if _space_re.search(key) is not None: | ||
- raise ValueError(f"Spaces are not allowed in attributes: '{key}'") | ||
+ if _attr_key_re.search(key) is not None: | ||
+ raise ValueError(f"Invalid character in attribute name: {key!r}") | ||
|
||
items.append(f'{escape(key)}="{escape(value)}"') | ||
|
||
-- | ||
2.45.2 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
From da58d627323696d5b0167cc9f1cc9e1070b5e18b Mon Sep 17 00:00:00 2001 | ||
From: Kanishk-Bansal <[email protected]> | ||
Date: Thu, 2 Jan 2025 14:24:25 +0000 | ||
Subject: [PATCH] fix CVE-2024-56201 | ||
|
||
--- | ||
src/jinja2/compiler.py | 7 ++++++- | ||
1 file changed, 6 insertions(+), 1 deletion(-) | ||
|
||
diff --git a/src/jinja2/compiler.py b/src/jinja2/compiler.py | ||
index 3458095..27d86c3 100644 | ||
--- a/src/jinja2/compiler.py | ||
+++ b/src/jinja2/compiler.py | ||
@@ -1122,9 +1122,14 @@ class CodeGenerator(NodeVisitor): | ||
) | ||
self.writeline(f"if {frame.symbols.ref(alias)} is missing:") | ||
self.indent() | ||
+ # The position will contain the template name, and will be formatted | ||
+ # into a string that will be compiled into an f-string. Curly braces | ||
+ # in the name must be replaced with escapes so that they will not be | ||
+ # executed as part of the f-string. | ||
+ position = self.position(node).replace("{", "{{").replace("}", "}}") | ||
message = ( | ||
"the template {included_template.__name__!r}" | ||
- f" (imported on {self.position(node)})" | ||
+ f" (imported on {position})" | ||
f" does not export the requested name {name!r}" | ||
) | ||
self.writeline( | ||
-- | ||
2.45.2 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
From 241312a0fb234989db874a723dbb2f05907796d3 Mon Sep 17 00:00:00 2001 | ||
From: Kanishk-Bansal <[email protected]> | ||
Date: Thu, 2 Jan 2025 14:40:27 +0000 | ||
Subject: [PATCH] Fix CVE-2024-56326 | ||
|
||
--- | ||
src/jinja2/sandbox.py | 75 +++++++++++++++++++++---------------------- | ||
1 file changed, 37 insertions(+), 38 deletions(-) | ||
|
||
diff --git a/src/jinja2/sandbox.py b/src/jinja2/sandbox.py | ||
index 06d7414..c3f4a33 100644 | ||
--- a/src/jinja2/sandbox.py | ||
+++ b/src/jinja2/sandbox.py | ||
@@ -7,6 +7,7 @@ import typing as t | ||
from _string import formatter_field_name_split # type: ignore | ||
from collections import abc | ||
from collections import deque | ||
+from functools import update_wrapper | ||
from string import Formatter | ||
|
||
from markupsafe import EscapeFormatter | ||
@@ -80,20 +81,6 @@ _mutable_spec: t.Tuple[t.Tuple[t.Type, t.FrozenSet[str]], ...] = ( | ||
) | ||
|
||
|
||
-def inspect_format_method(callable: t.Callable) -> t.Optional[str]: | ||
- if not isinstance( | ||
- callable, (types.MethodType, types.BuiltinMethodType) | ||
- ) or callable.__name__ not in ("format", "format_map"): | ||
- return None | ||
- | ||
- obj = callable.__self__ | ||
- | ||
- if isinstance(obj, str): | ||
- return obj | ||
- | ||
- return None | ||
- | ||
- | ||
def safe_range(*args: int) -> range: | ||
"""A range that can't generate ranges with a length of more than | ||
MAX_RANGE items. | ||
@@ -313,6 +300,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) | ||
@@ -330,6 +320,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) | ||
@@ -345,34 +338,43 @@ class SandboxedEnvironment(Environment): | ||
exc=SecurityError, | ||
) | ||
|
||
- def format_string( | ||
- self, | ||
- s: str, | ||
- args: t.Tuple[t.Any, ...], | ||
- kwargs: t.Dict[str, t.Any], | ||
- format_func: t.Optional[t.Callable] = None, | ||
- ) -> str: | ||
- """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: t.Any) -> t.Optional[t.Callable[..., str]]: | ||
+ """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 not isinstance( | ||
+ value, (types.MethodType, types.BuiltinMethodType) | ||
+ ) or value.__name__ not in ("format", "format_map"): | ||
+ return None | ||
+ f_self: t.Any = value.__self__ | ||
+ if not isinstance(f_self, str): | ||
+ return None | ||
+ str_type: t.Type[str] = type(f_self) | ||
+ is_format_map = value.__name__ == "format_map" | ||
formatter: SandboxedFormatter | ||
- if isinstance(s, Markup): | ||
- formatter = SandboxedEscapeFormatter(self, escape=s.escape) | ||
+ | ||
+ 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" | ||
- f" {len(args) + (kwargs is not None)} given" | ||
- ) | ||
+ vformat = formatter.vformat | ||
+ def wrapper(*args: t.Any, **kwargs: t.Any) -> str: | ||
+ 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 = () | ||
+ return str_type(vformat(f_self, args, kwargs)) | ||
|
||
- rv = formatter.vformat(s, args, kwargs) | ||
- return type(s)(rv) | ||
+ return update_wrapper(wrapper, value) | ||
|
||
def call( | ||
__self, # noqa: B902 | ||
@@ -382,9 +384,6 @@ class SandboxedEnvironment(Environment): | ||
**kwargs: t.Any, | ||
) -> t.Any: | ||
"""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. | ||
-- | ||
2.45.2 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,17 @@ | ||
Summary: A fast and easy to use template engine written in pure Python | ||
Name: python-jinja2 | ||
Version: 3.1.2 | ||
Release: 1%{?dist} | ||
Release: 2%{?dist} | ||
License: BSD | ||
Vendor: Microsoft Corporation | ||
Distribution: Azure Linux | ||
Group: Development/Languages/Python | ||
URL: https://jinja.pocoo.org/ | ||
Source0: https://files.pythonhosted.org/packages/source/j/jinja2/Jinja2-%{version}.tar.gz | ||
Patch0: CVE-2024-22195.patch | ||
Patch1: CVE-2024-34064.patch | ||
Patch2: CVE-2024-56201.patch | ||
Patch3: CVE-2024-56326.patch | ||
BuildArch: noarch | ||
|
||
%description | ||
|
@@ -33,7 +37,7 @@ inspired non-XML syntax but supports inline expressions and an optional | |
sandboxed environment. | ||
|
||
%prep | ||
%autosetup -n Jinja2-%{version} | ||
%autosetup -p1 -n Jinja2-%{version} | ||
sed -i 's/\r$//' LICENSE.rst # Fix wrong EOL encoding | ||
|
||
%build | ||
|
@@ -53,6 +57,9 @@ tox -e py%{python3_version_nodots} | |
%{python3_sitelib}/Jinja2-%{version}-py%{python3_version}.egg-info | ||
|
||
%changelog | ||
* Thu Jan 2 2025 Kanishk Bansal <[email protected]> - 3.1.2-2 | ||
- Address CVE-2024-22195, CVE-2024-34064, CVE-2024-56201, CVE-2024-56326 with an upstream patch. | ||
|
||
* Mon Nov 27 2023 Andrew Phelps <[email protected]> - 3.1.2-1 | ||
- Upgrade to version 3.1.2 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters