Django is one of the most popular Python web frameworks, powering thousands of websites. But in late 2021, a sneaky vulnerability was discovered in a tool developers often use during development: the {% debug %} template tag. If you’ve used Django versions prior to the fixed releases, you could have exposed your project to cross-site scripting (XSS) — even without realizing it.
Let’s walk through how CVE-2022-22818 works, what the risks are, and how you can make sure your site is secure.
What is CVE-2022-22818?
CVE-2022-22818 is a vulnerability disclosed in January 2022, affecting several versions of Django:
Django 4.: Before 4..2
The issue is with the {% debug %} template tag. This tag is used to print the current template context variables to the page — super handy while debugging! But, if untrusted user values are present in the context, this information could be dumped to the browser without proper escaping, allowing for XSS (cross-site scripting) attacks.
What’s the danger?
If your context has unsanitized user input, {% debug %} would output it as raw HTML. An attacker could inject <script> tags or malicious HTML, which would then run in the browser of anyone viewing that page — potentially stealing cookies, hijacking sessions, or more.
Explaining the Core Issue
Here’s a simple look at what happened under the hood.
Suppose you’re developing and use
{% debug %}
If your context includes something a user submitted — for example, request.GET['name'] with a value like <script>alert("xss")</script> — here’s an example template:
<h1>Hello, {{ name }}</h1>
{% debug %}
If you visit /welcome?name=<script>alert('XSSed')</script>, the output of {% debug %} would show
context = {
...
'name': "<script>alert('XSSed')</script>",
...
}
Because {% debug %} did not HTML-escape its output, this value is rendered raw in the browser. The attacker's script could execute as soon as the page loads.
Real-World Impact and Exploit
While the {% debug %} tag is intended for debugging and should not be present in production templates, it’s not uncommon for projects (especially those with less-experienced developers) to leave it in by mistake.
This makes CVE-2022-22818 a low-complexity, high-impact vulnerability:
Here’s a quick proof of concept you can try with an old Django project (be careful!)
1. Template Example — templates/debug_test.html:
Hi, {{ name }}
{% debug %}
`
http://127...1:800/debug_test?name=alert('pwned')
How was it fixed?
The Django team fixed this bug by ensuring the context displayed by {% debug %} is properly escaped. That means any HTML or JavaScript inserted via context variables gets shown as harmless text, not as executed code.
You can update Django with pip
pip install "django>=3.2.12"
# or pick the fixed version for your branch
References
- Django Security Advisory: CVE-2022-22818
- Django CVE-2022-22818 at MITRE
- Django issue tracker/PR
Recap
- {% debug %} in Django versions < 2.2.27, < 3.2.12, and < 4..2 can leak XSS if user data is in context.
Timeline
Published on: 02/03/2022 02:15:00 UTC
Last modified on: 02/22/2022 10:19:00 UTC