Skip to content

Commit 7167953

Browse files
authored
Merge pull request from GHSA-h5c8-rqwp-cp95
Raise an exception when spaces are used in HTML attribute keys generated by xmlattr
2 parents d84a174 + 7dd3680 commit 7167953

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Unreleased
77

88
- Fix compiler error when checking if required blocks in parent templates are
99
empty. :pr:`1858`
10+
- ``xmlattr`` filter does not allow keys with spaces. GHSA-h5c8-rqwp-cp95
1011

1112

1213
Version 3.1.2

src/jinja2/filters.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,17 @@ def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K
248248
yield from value.items()
249249

250250

251+
_space_re = re.compile(r"\s", flags=re.ASCII)
252+
253+
251254
@pass_eval_context
252255
def do_xmlattr(
253256
eval_ctx: "EvalContext", d: t.Mapping[str, t.Any], autospace: bool = True
254257
) -> str:
255258
"""Create an SGML/XML attribute string based on the items in a dict.
256-
All values that are neither `none` nor `undefined` are automatically
257-
escaped:
259+
260+
If any key contains a space, this fails with a ``ValueError``. Values that
261+
are neither ``none`` nor ``undefined`` are automatically escaped.
258262
259263
.. sourcecode:: html+jinja
260264
@@ -273,12 +277,22 @@ def do_xmlattr(
273277
274278
As you can see it automatically prepends a space in front of the item
275279
if the filter returned something unless the second parameter is false.
280+
281+
.. versionchanged:: 3.1.3
282+
Keys with spaces are not allowed.
276283
"""
277-
rv = " ".join(
278-
f'{escape(key)}="{escape(value)}"'
279-
for key, value in d.items()
280-
if value is not None and not isinstance(value, Undefined)
281-
)
284+
items = []
285+
286+
for key, value in d.items():
287+
if value is None or isinstance(value, Undefined):
288+
continue
289+
290+
if _space_re.search(key) is not None:
291+
raise ValueError(f"Spaces are not allowed in attributes: '{key}'")
292+
293+
items.append(f'{escape(key)}="{escape(value)}"')
294+
295+
rv = " ".join(items)
282296

283297
if autospace and rv:
284298
rv = " " + rv

tests/test_filters.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,12 @@ def test_xmlattr(self, env):
474474
assert 'bar="23"' in out
475475
assert 'blub:blub="<?>"' in out
476476

477+
def test_xmlattr_key_with_spaces(self, env):
478+
with pytest.raises(ValueError, match="Spaces are not allowed"):
479+
env.from_string(
480+
"{{ {'src=1 onerror=alert(1)': 'my_class'}|xmlattr }}"
481+
).render()
482+
477483
def test_sort1(self, env):
478484
tmpl = env.from_string("{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}")
479485
assert tmpl.render() == "[1, 2, 3]|[3, 2, 1]"

0 commit comments

Comments
 (0)