1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Fixed CVE-2024-53907 -- Mitigated potential DoS in strip_tags().

Thanks to jiangniao for the report, and Shai Berger and Natalia Bidart
for the reviews.
This commit is contained in:
Sarah Boyce
2024-11-13 15:06:23 +01:00
parent 58e548db8b
commit 49ff1042aa
5 changed files with 63 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ from collections.abc import Mapping
from html.parser import HTMLParser
from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit
from django.core.exceptions import SuspiciousOperation
from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.encoding import punycode
from django.utils.functional import Promise, cached_property, keep_lazy, keep_lazy_text
@@ -40,6 +41,7 @@ VOID_ELEMENTS = frozenset(
)
MAX_URL_LENGTH = 2048
MAX_STRIP_TAGS_DEPTH = 50
@keep_lazy(SafeString)
@@ -211,15 +213,19 @@ def _strip_once(value):
@keep_lazy_text
def strip_tags(value):
"""Return the given HTML with all tags stripped."""
# Note: in typical case this loop executes _strip_once once. Loop condition
# is redundant, but helps to reduce number of executions of _strip_once.
value = str(value)
# Note: in typical case this loop executes _strip_once twice (the second
# execution does not remove any more tags).
strip_tags_depth = 0
while "<" in value and ">" in value:
if strip_tags_depth >= MAX_STRIP_TAGS_DEPTH:
raise SuspiciousOperation
new_value = _strip_once(value)
if value.count("<") == new_value.count("<"):
# _strip_once wasn't able to detect more tags.
break
value = new_value
strip_tags_depth += 1
return value