]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
xmlattr filter disallows keys with spaces
authorCalum Hutton <calum.hutton@snyk.io>
Thu, 26 Oct 2023 11:08:53 +0000 (12:08 +0100)
committerDavid Lord <davidism@gmail.com>
Wed, 10 Jan 2024 22:01:13 +0000 (14:01 -0800)
CHANGES.rst
src/jinja2/filters.py
tests/test_filters.py

index 36db0843a5bf6a9f78d5f156bf2a592ada2f1983..d6688e762548169a28d6df4bcadf057030c4af42 100644 (file)
@@ -7,6 +7,7 @@ Unreleased
 
 -   Fix compiler error when checking if required blocks in parent templates are
     empty. :pr:`1858`
+-   ``xmlattr`` filter does not allow keys with spaces. GHSA-h5c8-rqwp-cp95
 
 
 Version 3.1.2
index ed07c4c0e2ae1b6203b3468cda8a303ecf3d7832..c7ecc9bb683085b9e1a54a03258e2e4967aad6d9 100644 (file)
@@ -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
index 32897c546e5a87403323e30d1c4d20db7e3eb5b8..f50ed13ab5e16022e95163cd77c500b57addc732 100644 (file)
@@ -474,6 +474,12 @@ class TestFilter:
         assert 'bar="23"' in out
         assert 'blub:blub="&lt;?&gt;"' 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) }}")
         assert tmpl.render() == "[1, 2, 3]|[3, 2, 1]"