+44
-4
lines changedFilter options
+44
-4
lines changed Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
7
7
from django.core.exceptions import ValidationError
8
8
from django.utils.deconstruct import deconstructible
9
9
from django.utils.encoding import punycode
10
+
from django.utils.http import MAX_URL_LENGTH
10
11
from django.utils.ipv6 import is_valid_ipv6_address
11
12
from django.utils.regex_helper import _lazy_re_compile
12
13
from django.utils.translation import gettext_lazy as _
@@ -155,7 +156,7 @@ class URLValidator(RegexValidator):
155
156
message = _("Enter a valid URL.")
156
157
schemes = ["http", "https", "ftp", "ftps"]
157
158
unsafe_chars = frozenset("\t\r\n")
158
-
max_length = 2048
159
+
max_length = MAX_URL_LENGTH
159
160
160
161
def __init__(self, schemes=None, **kwargs):
161
162
super().__init__(**kwargs)
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
11
11
from django.utils.deprecation import RemovedInDjango60Warning
12
12
from django.utils.encoding import punycode
13
13
from django.utils.functional import Promise, cached_property, keep_lazy, keep_lazy_text
14
-
from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS
14
+
from django.utils.http import MAX_URL_LENGTH, RFC3986_GENDELIMS, RFC3986_SUBDELIMS
15
15
from django.utils.regex_helper import _lazy_re_compile
16
16
from django.utils.safestring import SafeData, SafeString, mark_safe
17
17
from django.utils.text import normalize_newlines
@@ -39,7 +39,6 @@
39
39
)
40
40
)
41
41
42
-
MAX_URL_LENGTH = 2048
43
42
MAX_STRIP_TAGS_DEPTH = 50
44
43
45
44
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
37
37
38
38
RFC3986_GENDELIMS = ":/?#[]@"
39
39
RFC3986_SUBDELIMS = "!$&'()*+,;="
40
+
MAX_URL_LENGTH = 2048
40
41
41
42
42
43
def urlencode(query, doseq=False):
@@ -272,7 +273,10 @@ def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
272
273
def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
273
274
# Chrome considers any URL with more than two slashes to be absolute, but
274
275
# urlparse is not so flexible. Treat any url with three slashes as unsafe.
275
-
if url.startswith("///"):
276
+
if url.startswith("///") or len(url) > MAX_URL_LENGTH:
277
+
# urlparse does not perform validation of inputs. Unicode normalization
278
+
# is very slow on Windows and can be a DoS attack vector.
279
+
# https://docs.python.org/3/library/urllib.parse.html#url-parsing-security
276
280
return False
277
281
try:
278
282
url_info = urlparse(url)
Original file line number Diff line number Diff line change
@@ -5,3 +5,13 @@ Django 5.0.14 release notes
5
5
*April 2, 2025*
6
6
7
7
Django 5.0.14 fixes a security issue with severity "moderate" in 5.0.13.
8
+
9
+
CVE-2025-27556: Potential denial-of-service vulnerability in ``LoginView``, ``LogoutView``, and ``set_language()`` on Windows
10
+
=============================================================================================================================
11
+
12
+
Python's :func:`NFKC normalization <python:unicodedata.normalize>` is slow on
13
+
Windows. As a consequence, :class:`~django.contrib.auth.views.LoginView`,
14
+
:class:`~django.contrib.auth.views.LogoutView`, and
15
+
:func:`~django.views.i18n.set_language` were subject to a potential
16
+
denial-of-service attack via certain inputs with a very large number of Unicode
17
+
characters.
Original file line number Diff line number Diff line change
@@ -7,6 +7,16 @@ Django 5.1.8 release notes
7
7
Django 5.1.8 fixes a security issue with severity "moderate" and several bugs
8
8
in 5.1.7.
9
9
10
+
CVE-2025-27556: Potential denial-of-service vulnerability in ``LoginView``, ``LogoutView``, and ``set_language()`` on Windows
11
+
=============================================================================================================================
12
+
13
+
Python's :func:`NFKC normalization <python:unicodedata.normalize>` is slow on
14
+
Windows. As a consequence, :class:`~django.contrib.auth.views.LoginView`,
15
+
:class:`~django.contrib.auth.views.LogoutView`, and
16
+
:func:`~django.views.i18n.set_language` were subject to a potential
17
+
denial-of-service attack via certain inputs with a very large number of Unicode
18
+
characters.
19
+
10
20
Bugfixes
11
21
========
12
22
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
6
6
from django.test import SimpleTestCase
7
7
from django.utils.datastructures import MultiValueDict
8
8
from django.utils.http import (
9
+
MAX_URL_LENGTH,
9
10
base36_to_int,
10
11
content_disposition_header,
11
12
escape_leading_slashes,
@@ -273,6 +274,21 @@ def test_secure_param_non_https_urls(self):
273
274
False,
274
275
)
275
276
277
+
def test_max_url_length(self):
278
+
allowed_host = "example.com"
279
+
max_extra_characters = "é" * (MAX_URL_LENGTH - len(allowed_host) - 1)
280
+
max_length_boundary_url = f"{allowed_host}/{max_extra_characters}"
281
+
cases = [
282
+
(max_length_boundary_url, True),
283
+
(max_length_boundary_url + "ú", False),
284
+
]
285
+
for url, expected in cases:
286
+
with self.subTest(url=url):
287
+
self.assertIs(
288
+
url_has_allowed_host_and_scheme(url, allowed_hosts={allowed_host}),
289
+
expected,
290
+
)
291
+
276
292
277
293
class URLSafeBase64Tests(unittest.TestCase):
278
294
def test_roundtrip(self):
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4