VYPR
Moderate severityNVD Advisory· Published Oct 8, 2024· Updated Mar 17, 2025

CVE-2024-45230

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.

PackageAffected versionsPatched versions
DjangoPyPI
>= 5.1, < 5.1.15.1.1
DjangoPyPI
>= 5.0, < 5.0.95.0.9
DjangoPyPI
>= 4.2, < 4.2.164.2.16

Affected products

10

Patches

3
022ab0a75c76

[5.1.x] Fixed CVE-2024-45230 -- Mitigated potential DoS in urlize and urlizetrunc template filters.

https://github.com/django/djangoSarah BoyceAug 12, 2024via ghsa
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=&amp;</a>;;",
             )
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp.;...;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp</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.

https://github.com/django/djangoSarah BoyceAug 12, 2024via ghsa
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>.,:;)&quot;!",
             )
     
    +    def test_trailing_semicolon(self):
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp;</a>",
    +        )
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp;;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp;</a>;",
    +        )
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp;;;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp;</a>;;",
    +        )
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp.;...;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp</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.

https://github.com/django/djangoSarah BoyceAug 12, 2024via ghsa
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>.,:;)&quot;!",
             )
     
    +    def test_trailing_semicolon(self):
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp;</a>",
    +        )
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp;;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp;</a>;",
    +        )
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp;;;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp;</a>;;",
    +        )
    +        self.assertEqual(
    +            urlize("http://example.com?x=&amp.;...;", autoescape=False),
    +            '<a href="http://example.com?x=" rel="nofollow">'
    +            "http://example.com?x=&amp</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

News mentions

0

No linked articles in our index yet.