Skip to content

Commit c27a7eb

Browse files
MarkusHadamchainz
authored andcommitted
[2.2.x] Fixed CVE-2022-22818 -- Fixed possible XSS via {% debug %} template tag.
Thanks Keryn Knight for the report. Backport of 394517f from main. Co-authored-by: Adam Johnson <me@adamj.eu>
1 parent 4cafd3a commit c27a7eb

File tree

5 files changed

+68
-15
lines changed

5 files changed

+68
-15
lines changed

django/template/defaulttags.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from django.conf import settings
1010
from django.utils import timezone
11-
from django.utils.html import conditional_escape, format_html
11+
from django.utils.html import conditional_escape, escape, format_html
1212
from django.utils.lorem_ipsum import paragraphs, words
1313
from django.utils.safestring import mark_safe
1414

@@ -94,10 +94,13 @@ def reset(self, context):
9494

9595
class DebugNode(Node):
9696
def render(self, context):
97+
if not settings.DEBUG:
98+
return ''
99+
97100
from pprint import pformat
98-
output = [pformat(val) for val in context]
101+
output = [escape(pformat(val)) for val in context]
99102
output.append('\n\n')
100-
output.append(pformat(sys.modules))
103+
output.append(escape(pformat(sys.modules)))
101104
return ''.join(output)
102105

103106

docs/ref/templates/builtins.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,13 @@ from its first value when it's next encountered.
194194
---------
195195

196196
Outputs a whole load of debugging information, including the current context
197-
and imported modules.
197+
and imported modules. ``{% debug %}`` outputs nothing when the :setting:`DEBUG`
198+
setting is ``False``.
199+
200+
.. versionchanged:: 2.2.27
201+
202+
In older versions, debugging information was displayed when the
203+
:setting:`DEBUG` setting was ``False``.
198204

199205
.. templatetag:: extends
200206

docs/releases/2.2.27.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@ Django 2.2.27 release notes
66

77
Django 2.2.27 fixes two security issues with severity "medium" in 2.2.26.
88

9-
...
9+
CVE-2022-22818: Possible XSS via ``{% debug %}`` template tag
10+
=============================================================
11+
12+
The ``{% debug %}`` template tag didn't properly encode the current context,
13+
posing an XSS attack vector.
14+
15+
In order to avoid this vulnerability, ``{% debug %}`` no longer outputs an
16+
information when the ``DEBUG`` setting is ``False``, and it ensures all context
17+
variables are correctly escaped when the ``DEBUG`` setting is ``True``.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from django.contrib.auth.models import Group
2+
from django.test import SimpleTestCase, override_settings
3+
4+
from ..utils import setup
5+
6+
7+
@override_settings(DEBUG=True)
8+
class DebugTests(SimpleTestCase):
9+
10+
@override_settings(DEBUG=False)
11+
@setup({'non_debug': '{% debug %}'})
12+
def test_non_debug(self):
13+
output = self.engine.render_to_string('non_debug', {})
14+
self.assertEqual(output, '')
15+
16+
@setup({'modules': '{% debug %}'})
17+
def test_modules(self):
18+
output = self.engine.render_to_string('modules', {})
19+
self.assertIn(
20+
'&#39;django&#39;: &lt;module &#39;django&#39; ',
21+
output,
22+
)
23+
24+
@setup({'plain': '{% debug %}'})
25+
def test_plain(self):
26+
output = self.engine.render_to_string('plain', {'a': 1})
27+
self.assertTrue(output.startswith(
28+
'{&#39;a&#39;: 1}'
29+
'{&#39;False&#39;: False, &#39;None&#39;: None, '
30+
'&#39;True&#39;: True}\n\n{'
31+
))
32+
33+
@setup({'non_ascii': '{% debug %}'})
34+
def test_non_ascii(self):
35+
group = Group(name="清風")
36+
output = self.engine.render_to_string('non_ascii', {'group': group})
37+
self.assertTrue(output.startswith(
38+
'{&#39;group&#39;: &lt;Group: 清風&gt;}'
39+
))
40+
41+
@setup({'script': '{% debug %}'})
42+
def test_script(self):
43+
output = self.engine.render_to_string('script', {'frag': '<script>'})
44+
self.assertTrue(output.startswith(
45+
'{&#39;frag&#39;: &#39;&lt;script&gt;&#39;}'
46+
))

tests/template_tests/tests.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import sys
22

3-
from django.contrib.auth.models import Group
43
from django.template import Context, Engine, TemplateSyntaxError
54
from django.template.base import UNKNOWN_SOURCE
65
from django.test import SimpleTestCase, override_settings
@@ -143,15 +142,6 @@ def test_super_errors(self):
143142
with self.assertRaises(NoReverseMatch):
144143
t.render(Context())
145144

146-
def test_debug_tag_non_ascii(self):
147-
"""
148-
#23060 -- Test non-ASCII model representation in debug output.
149-
"""
150-
group = Group(name="清風")
151-
c1 = Context({"objs": [group]})
152-
t1 = Engine().from_string('{% debug %}')
153-
self.assertIn("清風", t1.render(c1))
154-
155145
def test_extends_generic_template(self):
156146
"""
157147
#24338 -- Allow extending django.template.backends.django.Template

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy