diff -Nru jinja2-2.10.1/debian/changelog jinja2-2.10.1/debian/changelog --- jinja2-2.10.1/debian/changelog 2020-02-27 10:49:32.000000000 +0000 +++ jinja2-2.10.1/debian/changelog 2024-01-22 10:14:05.000000000 +0000 @@ -1,3 +1,16 @@ +jinja2 (2.10.1-2ubuntu0.2) focal-security; urgency=medium + + * SECURITY UPDATE: regular expression DoS + - debian/patches/CVE-2020-28493.patch: rewrite regex match for + punctuation in urlize() in jinja2/utils.py. + - CVE-2020-28493 + * SECURITY UPDATE: Cross-Site scripting + - debian/patches/CVE-2024-22195.patch: disallow keys with spaces + in jinja2/filters.py, tests/test_filters.py. + - CVE-2024-22195 + + -- Leonidas Da Silva Barbosa Mon, 22 Jan 2024 07:14:05 -0300 + jinja2 (2.10.1-2) unstable; urgency=medium [ Ondřej Nový ] diff -Nru jinja2-2.10.1/debian/control jinja2-2.10.1/debian/control --- jinja2-2.10.1/debian/control 2020-02-27 10:49:32.000000000 +0000 +++ jinja2-2.10.1/debian/control 2024-01-22 10:14:05.000000000 +0000 @@ -1,7 +1,8 @@ Source: jinja2 Section: python Priority: optional -Maintainer: Piotr Ożarowski +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Piotr Ożarowski Uploaders: Debian Python Modules Team Build-Depends: debhelper-compat (= 9), dh-python, python-all (>= 2.6.6-3), python3-all, diff -Nru jinja2-2.10.1/debian/patches/CVE-2020-28493.patch jinja2-2.10.1/debian/patches/CVE-2020-28493.patch --- jinja2-2.10.1/debian/patches/CVE-2020-28493.patch 1970-01-01 00:00:00.000000000 +0000 +++ jinja2-2.10.1/debian/patches/CVE-2020-28493.patch 2024-01-22 10:14:05.000000000 +0000 @@ -0,0 +1,121 @@ +From ef658dc3b6389b091d608e710a810ce8b87995b3 Mon Sep 17 00:00:00 2001 +From: David Lord +Date: Sun, 31 Jan 2021 07:54:40 -0800 +Subject: [PATCH] speed up urlize matching +Index: jinja2-2.10.1/jinja2/utils.py +=================================================================== +--- jinja2-2.10.1.orig/jinja2/utils.py ++++ jinja2-2.10.1/jinja2/utils.py +@@ -20,20 +20,10 @@ except: + from threading import Lock + from jinja2._compat import text_type, string_types, implements_iterator, \ + url_quote ++from string import ascii_letters as _letters ++from string import digits as _digits + + +-_word_split_re = re.compile(r'(\s+)') +-_punctuation_re = re.compile( +- '^(?P(?:%s)*)(?P.*?)(?P(?:%s)*)$' % ( +- '|'.join(map(re.escape, ('(', '<', '<'))), +- '|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '>'))) +- ) +-) +-_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$') +-_striptags_re = re.compile(r'(|<[^>]*>)') +-_entity_re = re.compile(r'&([^;]+);') +-_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +-_digits = '0123456789' + + # special singleton representing missing values for the runtime + missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})() +@@ -208,35 +198,65 @@ def urlize(text, trim_url_limit=None, re + trim_url = lambda x, limit=trim_url_limit: limit is not None \ + and (x[:limit] + (len(x) >=limit and '...' + or '')) or x +- words = _word_split_re.split(text_type(escape(text))) ++ words = re.split(r"(\s+)", text_type(escape(text))) + rel_attr = rel and ' rel="%s"' % text_type(escape(rel)) or '' + target_attr = target and ' target="%s"' % escape(target) or '' + + for i, word in enumerate(words): +- match = _punctuation_re.match(word) ++ head, middle, tail = "", word, "" ++ match = re.match(r"^([(<]|<)+", middle) ++ + if match: +- lead, middle, trail = match.groups() +- if middle.startswith('www.') or ( +- '@' not in middle and +- not middle.startswith('http://') and +- not middle.startswith('https://') and +- len(middle) > 0 and +- middle[0] in _letters + _digits and ( +- middle.endswith('.org') or +- middle.endswith('.net') or +- middle.endswith('.com') +- )): +- middle = '%s' % (middle, +- rel_attr, target_attr, trim_url(middle)) +- if middle.startswith('http://') or \ +- middle.startswith('https://'): +- middle = '%s' % (middle, +- rel_attr, target_attr, trim_url(middle)) +- if '@' in middle and not middle.startswith('www.') and \ +- not ':' in middle and _simple_email_re.match(middle): +- middle = '%s' % (middle, middle) +- if lead + middle + trail != word: +- words[i] = lead + middle + trail ++ head = match.group() ++ middle = middle[match.end() :] ++ ++ # Unlike lead, which is anchored to the start of the string, ++ # need to check that the string ends with any of the characters ++ # before trying to match all of them, to avoid backtracking. ++ if middle.endswith((")", ">", ".", ",", "\n", ">")): ++ match = re.search(r"([)>.,\n]|>)+$", middle) ++ ++ if match: ++ tail = match.group() ++ middle = middle[: match.start()] ++ ++ if middle.startswith("www.") or ( ++ "@" not in middle ++ and not middle.startswith("http://") ++ and not middle.startswith("https://") ++ and len(middle) > 0 ++ and middle[0] in _letters + _digits ++ and ( ++ middle.endswith(".org") ++ or middle.endswith(".net") ++ or middle.endswith(".com") ++ ) ++ ): ++ middle = '%s' % ( ++ middle, ++ rel_attr, ++ target_attr, ++ trim_url(middle), ++ ) ++ ++ if middle.startswith("http://") or middle.startswith("https://"): ++ middle = '%s' % ( ++ middle, ++ rel_attr, ++ target_attr, ++ trim_url(middle), ++ ) ++ ++ if ( ++ "@" in middle ++ and not middle.startswith("www.") ++ and ":" not in middle ++ and re.match(r"^\S+@\w[\w.-]*\.\w+$", middle) ++ ): ++ middle = '%s' % (middle, middle) ++ ++ words[i] = head + middle + tail ++ + return u''.join(words) + + diff -Nru jinja2-2.10.1/debian/patches/CVE-2024-22195.patch jinja2-2.10.1/debian/patches/CVE-2024-22195.patch --- jinja2-2.10.1/debian/patches/CVE-2024-22195.patch 1970-01-01 00:00:00.000000000 +0000 +++ jinja2-2.10.1/debian/patches/CVE-2024-22195.patch 2024-01-22 10:14:05.000000000 +0000 @@ -0,0 +1,83 @@ +From 7dd3680e6eea0d77fde024763657aa4d884ddb23 Mon Sep 17 00:00:00 2001 +From: Calum Hutton +Date: Thu, 26 Oct 2023 12:08:53 +0100 +Subject: [PATCH] xmlattr filter disallows keys with spaces +diff --git a/jinja2/filters.py b/jinja2/filters.py +index 3b0456d..94635a6 100644 +--- a/jinja2/filters.py ++++ b/jinja2/filters.py +@@ -9,6 +9,7 @@ + :license: BSD, see LICENSE for more details. + """ + import re ++import sys + import math + import random + import warnings +@@ -154,12 +155,20 @@ def do_lower(s): + """Convert a value to lowercase.""" + return soft_unicode(s).lower() + ++py_vers = sys.version_info.major ++if py_vers == 3: ++ _space_re = re.compile(r"\s", flags=re.ASCII) ++elif py_vers == 2: ++ _space_re = re.compile(r'[\t\n\x0B\x0C\r\x20]+') ++ ++ + + @evalcontextfilter + def do_xmlattr(_eval_ctx, d, autospace=True): + """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 + +@@ -178,12 +187,21 @@ def do_xmlattr(_eval_ctx, d, autospace=True): + + 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. ++ Keys with spaces are not allowed. + """ +- rv = u' '.join( +- u'%s="%s"' % (escape(key), escape(value)) +- for key, value in iteritems(d) +- 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("Spaces are not allowed in attributes: '%s'" % key) ++ ++ items.append('%s="%s"' % (escape(key), escape(value))) ++ ++ rv = " ".join(items) ++ + if autospace and rv: + rv = u' ' + rv + if _eval_ctx.autoescape: +diff --git a/tests/test_filters.py b/tests/test_filters.py +index 8962ced..911d10a 100644 +--- a/tests/test_filters.py ++++ b/tests/test_filters.py +@@ -389,6 +389,12 @@ def test_xmlattr(self, env): + assert 'bar="23"' in out + assert 'blub:blub="<?>"' in out + ++ def test_xmlattr_key_with_spaces(self, env): ++ with pytest.raises(ValueError, match="Spaces are not allowed"): ++ env.from_string( ++ "{{ {'src=1 onerror=alert(1)': 'my_class'}|xmlattr }}" ++ ).render() ++ + def test_sort1(self, env): + tmpl = env.from_string( + '{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}') diff -Nru jinja2-2.10.1/debian/patches/series jinja2-2.10.1/debian/patches/series --- jinja2-2.10.1/debian/patches/series 2020-02-27 10:49:32.000000000 +0000 +++ jinja2-2.10.1/debian/patches/series 2024-01-22 10:14:05.000000000 +0000 @@ -1 +1,3 @@ py3.9-fix-collections-import.patch +CVE-2024-22195.patch +CVE-2020-28493.patch