Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit edc2716

Browse files
committed
[5.1.x] Fixed CVE-2025-27556 -- Mitigated potential DoS in url_has_allowed_host_and_scheme() on Windows.
Thank you sw0rd1ight for the report. Backport of 39e2297 from main.
1 parent b3b09dc commit edc2716

File tree

6 files changed

+44
-4
lines changed

6 files changed

+44
-4
lines changed

django/core/validators.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.core.exceptions import ValidationError
88
from django.utils.deconstruct import deconstructible
99
from django.utils.encoding import punycode
10+
from django.utils.http import MAX_URL_LENGTH
1011
from django.utils.ipv6 import is_valid_ipv6_address
1112
from django.utils.regex_helper import _lazy_re_compile
1213
from django.utils.translation import gettext_lazy as _
@@ -155,7 +156,7 @@ class URLValidator(RegexValidator):
155156
message = _("Enter a valid URL.")
156157
schemes = ["http", "https", "ftp", "ftps"]
157158
unsafe_chars = frozenset("\t\r\n")
158-
max_length = 2048
159+
max_length = MAX_URL_LENGTH
159160

160161
def __init__(self, schemes=None, **kwargs):
161162
super().__init__(**kwargs)

django/utils/html.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from django.utils.deprecation import RemovedInDjango60Warning
1212
from django.utils.encoding import punycode
1313
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
1515
from django.utils.regex_helper import _lazy_re_compile
1616
from django.utils.safestring import SafeData, SafeString, mark_safe
1717
from django.utils.text import normalize_newlines
@@ -39,7 +39,6 @@
3939
)
4040
)
4141

42-
MAX_URL_LENGTH = 2048
4342
MAX_STRIP_TAGS_DEPTH = 50
4443

4544

django/utils/http.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
RFC3986_GENDELIMS = ":/?#[]@"
3939
RFC3986_SUBDELIMS = "!$&'()*+,;="
40+
MAX_URL_LENGTH = 2048
4041

4142

4243
def urlencode(query, doseq=False):
@@ -272,7 +273,10 @@ def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
272273
def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
273274
# Chrome considers any URL with more than two slashes to be absolute, but
274275
# 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
276280
return False
277281
try:
278282
url_info = urlparse(url)

docs/releases/5.0.14.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,13 @@ Django 5.0.14 release notes
55
*April 2, 2025*
66

77
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.

docs/releases/5.1.8.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ Django 5.1.8 release notes
77
Django 5.1.8 fixes a security issue with severity "moderate" and several bugs
88
in 5.1.7.
99

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+
1020
Bugfixes
1121
========
1222

tests/utils_tests/test_http.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.test import SimpleTestCase
77
from django.utils.datastructures import MultiValueDict
88
from django.utils.http import (
9+
MAX_URL_LENGTH,
910
base36_to_int,
1011
content_disposition_header,
1112
escape_leading_slashes,
@@ -273,6 +274,21 @@ def test_secure_param_non_https_urls(self):
273274
False,
274275
)
275276

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+
276292

277293
class URLSafeBase64Tests(unittest.TestCase):
278294
def test_roundtrip(self):

0 commit comments

Comments
 (0)