CVE-2024-45230
Description
An issue was discovered in Django 5.1 before 5.1.1, 5.0 before 5.0.9, and 4.2 before 4.2.16. The urlize() and urlizetrunc() template filters are subject to a potential denial-of-service attack via very large inputs with a specific sequence of characters.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Django's urlize() and urlizetrunc() template filters are vulnerable to a denial-of-service attack via large inputs with a specific character sequence.
Vulnerability
Description
An issue was discovered in Django versions 5.1 before 5.1.1, 5.0 before 5.0.9, and 4.2 before 4.2.16. The urlize() and urlizetrunc() template filters are susceptible to a denial-of-service (DoS) attack when processing very large inputs containing a specific sequence of characters [1][4]. The root cause lies in the trim_punctuation method, which inefficiently handles trailing punctuation and HTML entity detection, leading to excessive processing time [2][3].
Exploitation and
Attack Surface
An attacker can exploit this vulnerability by providing a crafted, large input string to a Django template that uses either the urlize or urlizetrunc filter. These filters are commonly applied to user-controlled content, such as data stored in a TextField or output from comment forms [2][3]. The attack does not require authentication if the filter is exposed to unauthenticated users. A network-adjacent attacker could cause resource exhaustion by submitting a specially crafted payload that triggers the performance penalty [1][4].
Impact
Successful exploitation results in a denial-of-service condition, where the server consumes excessive CPU resources to process the input, potentially making the application unresponsive [1][4]. This could lead to temporary service disruption for legitimate users.
Mitigation
Django has released patched versions (5.1.1, 5.0.9, 4.2.16) that fix the vulnerability by optimizing the trim_punctuation method and adding a warning about the performance impact [2][3]. As a workaround, administrators can limit the length of inputs passed to urlize using the truncatechars filter (e.g., {{ value|truncatechars:500|urlize }}) to reduce the risk [2][3].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
DjangoPyPI | >= 5.1, < 5.1.1 | 5.1.1 |
DjangoPyPI | >= 5.0, < 5.0.9 | 5.0.9 |
DjangoPyPI | >= 4.2, < 4.2.16 | 4.2.16 |
Affected products
10- Django/Djangodescription
- osv-coords9 versionspkg:bitnami/djangopkg:pypi/djangopkg:rpm/opensuse/python-Django4&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/python-Django6&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/python-Django&distro=openSUSE%20Leap%2015.5pkg:rpm/opensuse/python-Django&distro=openSUSE%20Leap%2015.6pkg:rpm/opensuse/python-Django&distro=openSUSE%20Tumbleweedpkg:rpm/suse/python-Django&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Package%20Hub%2015%20SP6pkg:rpm/suse/python-Django&distro=SUSE%20Package%20Hub%2015%20SP5
>= 4.2.0, < 4.2.16+ 8 more
- (no CPE)range: >= 4.2.0, < 4.2.16
- (no CPE)range: >= 5.1, < 5.1.1
- (no CPE)range: < 4.2.16-1.1
- (no CPE)range: < 6.0-1.1
- (no CPE)range: < 2.0.7-150000.1.33.1
- (no CPE)range: < 4.2.11-150600.3.9.1
- (no CPE)range: < 5.1.1-1.1
- (no CPE)range: < 4.2.11-150600.3.9.1
- (no CPE)range: < 2.2.28-bp155.7.18.1
Patches
3022ab0a75c76[5.1.x] Fixed CVE-2024-45230 -- Mitigated potential DoS in urlize and urlizetrunc template filters.
7 files changed · +46 −9
django/utils/html.py+10 −7 modified@@ -428,14 +428,17 @@ def trim_punctuation(self, word): potential_entity = middle[amp:] escaped = html.unescape(potential_entity) if escaped == potential_entity or escaped.endswith(";"): - rstripped = middle.rstrip(";") - amount_stripped = len(middle) - len(rstripped) - if amp > -1 and amount_stripped > 1: - # Leave a trailing semicolon as might be an entity. - trail = middle[len(rstripped) + 1 :] + trail - middle = rstripped + ";" + rstripped = middle.rstrip(self.trailing_punctuation_chars) + trail_start = len(rstripped) + amount_trailing_semicolons = len(middle) - len(middle.rstrip(";")) + if amp > -1 and amount_trailing_semicolons > 1: + # Leave up to most recent semicolon as might be an entity. + recent_semicolon = middle[trail_start:].index(";") + middle_semicolon_index = recent_semicolon + trail_start + 1 + trail = middle[middle_semicolon_index:] + trail + middle = rstripped + middle[trail_start:middle_semicolon_index] else: - trail = middle[len(rstripped) :] + trail + trail = middle[trail_start:] + trail middle = rstripped trimmed_something = True
docs/ref/templates/builtins.txt+11 −0 modified@@ -2932,6 +2932,17 @@ Django's built-in :tfilter:`escape` filter. The default value for email addresses that contain single quotes (``'``), things won't work as expected. Apply this filter only to plain text. +.. warning:: + + Using ``urlize`` or ``urlizetrunc`` can incur a performance penalty, which + can become severe when applied to user controlled values such as content + stored in a :class:`~django.db.models.TextField`. You can use + :tfilter:`truncatechars` to add a limit to such inputs: + + .. code-block:: html+django + + {{ value|truncatechars:500|urlize }} + .. templatefilter:: urlizetrunc ``urlizetrunc``
docs/releases/4.2.16.txt+6 −1 modified@@ -7,4 +7,9 @@ Django 4.2.16 release notes Django 4.2.16 fixes one security issue with severity "moderate" and one security issue with severity "low" in 4.2.15. -... +CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` +=========================================================================================== + +:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential +denial-of-service attack via very large inputs with a specific sequence of +characters.
docs/releases/5.0.9.txt+6 −1 modified@@ -7,4 +7,9 @@ Django 5.0.9 release notes Django 5.0.9 fixes one security issue with severity "moderate" and one security issue with severity "low" in 5.0.8. -... +CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` +=========================================================================================== + +:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential +denial-of-service attack via very large inputs with a specific sequence of +characters.
docs/releases/5.1.1.txt+7 −0 modified@@ -7,6 +7,13 @@ Django 5.1.1 release notes Django 5.1.1 fixes one security issue with severity "moderate", one security issue with severity "low", and several bugs in 5.1. +CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` +=========================================================================================== + +:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential +denial-of-service attack via very large inputs with a specific sequence of +characters. + Bugfixes ========
tests/template_tests/filter_tests/test_urlize.py+5 −0 modified@@ -321,6 +321,11 @@ def test_trailing_semicolon(self): '<a href="http://example.com?x=" rel="nofollow">' "http://example.com?x=&</a>;;", ) + self.assertEqual( + urlize("http://example.com?x=&.;...;", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>.;...;", + ) def test_brackets(self): """
tests/utils_tests/test_html.py+1 −0 modified@@ -375,6 +375,7 @@ def test_urlize_unchanged_inputs(self): "&:" + ";" * 100_000, "&.;" * 100_000, ".;" * 100_000, + "&" + ";:" * 100_000, ) for value in tests: with self.subTest(value=value):
d147a8ebbdf2[4.2.x] Fixed CVE-2024-45230 -- Mitigated potential DoS in urlize and urlizetrunc template filters.
5 files changed · +50 −8
django/utils/html.py+10 −7 modified@@ -395,14 +395,17 @@ def trim_punctuation(self, word): potential_entity = middle[amp:] escaped = html.unescape(potential_entity) if escaped == potential_entity or escaped.endswith(";"): - rstripped = middle.rstrip(";") - amount_stripped = len(middle) - len(rstripped) - if amp > -1 and amount_stripped > 1: - # Leave a trailing semicolon as might be an entity. - trail = middle[len(rstripped) + 1 :] + trail - middle = rstripped + ";" + rstripped = middle.rstrip(self.trailing_punctuation_chars) + trail_start = len(rstripped) + amount_trailing_semicolons = len(middle) - len(middle.rstrip(";")) + if amp > -1 and amount_trailing_semicolons > 1: + # Leave up to most recent semicolon as might be an entity. + recent_semicolon = middle[trail_start:].index(";") + middle_semicolon_index = recent_semicolon + trail_start + 1 + trail = middle[middle_semicolon_index:] + trail + middle = rstripped + middle[trail_start:middle_semicolon_index] else: - trail = middle[len(rstripped) :] + trail + trail = middle[trail_start:] + trail middle = rstripped trimmed_something = True
docs/ref/templates/builtins.txt+11 −0 modified@@ -2831,6 +2831,17 @@ Django's built-in :tfilter:`escape` filter. The default value for email addresses that contain single quotes (``'``), things won't work as expected. Apply this filter only to plain text. +.. warning:: + + Using ``urlize`` or ``urlizetrunc`` can incur a performance penalty, which + can become severe when applied to user controlled values such as content + stored in a :class:`~django.db.models.TextField`. You can use + :tfilter:`truncatechars` to add a limit to such inputs: + + .. code-block:: html+django + + {{ value|truncatechars:500|urlize }} + .. templatefilter:: urlizetrunc ``urlizetrunc``
docs/releases/4.2.16.txt+6 −1 modified@@ -7,4 +7,9 @@ Django 4.2.16 release notes Django 4.2.16 fixes one security issue with severity "moderate" and one security issue with severity "low" in 4.2.15. -... +CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` +=========================================================================================== + +:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential +denial-of-service attack via very large inputs with a specific sequence of +characters.
tests/template_tests/filter_tests/test_urlize.py+22 −0 modified@@ -305,6 +305,28 @@ def test_trailing_multiple_punctuation(self): "http://testing.com/example</a>.,:;)"!", ) + def test_trailing_semicolon(self): + self.assertEqual( + urlize("http://example.com?x=&", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>", + ) + self.assertEqual( + urlize("http://example.com?x=&;", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>;", + ) + self.assertEqual( + urlize("http://example.com?x=&;;", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>;;", + ) + self.assertEqual( + urlize("http://example.com?x=&.;...;", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>.;...;", + ) + def test_brackets(self): """ #19070 - Check urlize handles brackets properly
tests/utils_tests/test_html.py+1 −0 modified@@ -364,6 +364,7 @@ def test_urlize_unchanged_inputs(self): "&:" + ";" * 100_000, "&.;" * 100_000, ".;" * 100_000, + "&" + ";:" * 100_000, ) for value in tests: with self.subTest(value=value):
813de2672bd7[5.0.x] Fixed CVE-2024-45230 -- Mitigated potential DoS in urlize and urlizetrunc template filters.
6 files changed · +56 −9
django/utils/html.py+10 −7 modified@@ -425,14 +425,17 @@ def trim_punctuation(self, word): potential_entity = middle[amp:] escaped = html.unescape(potential_entity) if escaped == potential_entity or escaped.endswith(";"): - rstripped = middle.rstrip(";") - amount_stripped = len(middle) - len(rstripped) - if amp > -1 and amount_stripped > 1: - # Leave a trailing semicolon as might be an entity. - trail = middle[len(rstripped) + 1 :] + trail - middle = rstripped + ";" + rstripped = middle.rstrip(self.trailing_punctuation_chars) + trail_start = len(rstripped) + amount_trailing_semicolons = len(middle) - len(middle.rstrip(";")) + if amp > -1 and amount_trailing_semicolons > 1: + # Leave up to most recent semicolon as might be an entity. + recent_semicolon = middle[trail_start:].index(";") + middle_semicolon_index = recent_semicolon + trail_start + 1 + trail = middle[middle_semicolon_index:] + trail + middle = rstripped + middle[trail_start:middle_semicolon_index] else: - trail = middle[len(rstripped) :] + trail + trail = middle[trail_start:] + trail middle = rstripped trimmed_something = True
docs/ref/templates/builtins.txt+11 −0 modified@@ -2855,6 +2855,17 @@ Django's built-in :tfilter:`escape` filter. The default value for email addresses that contain single quotes (``'``), things won't work as expected. Apply this filter only to plain text. +.. warning:: + + Using ``urlize`` or ``urlizetrunc`` can incur a performance penalty, which + can become severe when applied to user controlled values such as content + stored in a :class:`~django.db.models.TextField`. You can use + :tfilter:`truncatechars` to add a limit to such inputs: + + .. code-block:: html+django + + {{ value|truncatechars:500|urlize }} + .. templatefilter:: urlizetrunc ``urlizetrunc``
docs/releases/4.2.16.txt+6 −1 modified@@ -7,4 +7,9 @@ Django 4.2.16 release notes Django 4.2.16 fixes one security issue with severity "moderate" and one security issue with severity "low" in 4.2.15. -... +CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` +=========================================================================================== + +:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential +denial-of-service attack via very large inputs with a specific sequence of +characters.
docs/releases/5.0.9.txt+6 −1 modified@@ -7,4 +7,9 @@ Django 5.0.9 release notes Django 5.0.9 fixes one security issue with severity "moderate" and one security issue with severity "low" in 5.0.8. -... +CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` +=========================================================================================== + +:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential +denial-of-service attack via very large inputs with a specific sequence of +characters.
tests/template_tests/filter_tests/test_urlize.py+22 −0 modified@@ -305,6 +305,28 @@ def test_trailing_multiple_punctuation(self): "http://testing.com/example</a>.,:;)"!", ) + def test_trailing_semicolon(self): + self.assertEqual( + urlize("http://example.com?x=&", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>", + ) + self.assertEqual( + urlize("http://example.com?x=&;", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>;", + ) + self.assertEqual( + urlize("http://example.com?x=&;;", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>;;", + ) + self.assertEqual( + urlize("http://example.com?x=&.;...;", autoescape=False), + '<a href="http://example.com?x=" rel="nofollow">' + "http://example.com?x=&</a>.;...;", + ) + def test_brackets(self): """ #19070 - Check urlize handles brackets properly
tests/utils_tests/test_html.py+1 −0 modified@@ -374,6 +374,7 @@ def test_urlize_unchanged_inputs(self): "&:" + ";" * 100_000, "&.;" * 100_000, ".;" * 100_000, + "&" + ";:" * 100_000, ) for value in tests: with self.subTest(value=value):
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- github.com/advisories/GHSA-5hgc-2vfp-mqvcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-45230ghsaADVISORY
- docs.djangoproject.com/en/dev/releases/securityghsaWEB
- github.com/django/django/commit/022ab0a75c76ab2ea31dfcc5f2cf5501e378d397ghsaWEB
- github.com/django/django/commit/813de2672bd7361e9a453ab62cd6e52f96b6525bghsaWEB
- github.com/django/django/commit/d147a8ebbdf28c17cafbbe2884f0bc57e2bf82e2ghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2024-102.yamlghsaWEB
- groups.google.com/forum/ghsaWEB
- www.djangoproject.com/weblog/2024/sep/03/security-releasesghsaWEB
- docs.djangoproject.com/en/dev/releases/security/mitre
- www.djangoproject.com/weblog/2024/sep/03/security-releases/mitre
News mentions
0No linked articles in our index yet.