diff options
| author | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-03-06 15:24:56 +0100 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-04-02 10:28:26 +0200 |
| commit | edc2716d01a6fdd84b173c02031695231bcee1f8 (patch) | |
| tree | 508f796fa9d4cf3eb7804dffd29dfbb7e9b2b118 /django | |
| parent | b3b09dc6ce72f2aa778b95dc988653bf8c034035 (diff) | |
[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 39e2297210d9d2938c75fc911d45f0e863dc4821 from main.
Diffstat (limited to 'django')
| -rw-r--r-- | django/core/validators.py | 3 | ||||
| -rw-r--r-- | django/utils/html.py | 3 | ||||
| -rw-r--r-- | django/utils/http.py | 6 |
3 files changed, 8 insertions, 4 deletions
diff --git a/django/core/validators.py b/django/core/validators.py index 8732ddf7ad..2979f3aefd 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -7,6 +7,7 @@ from urllib.parse import urlsplit, urlunsplit from django.core.exceptions import ValidationError from django.utils.deconstruct import deconstructible from django.utils.encoding import punycode +from django.utils.http import MAX_URL_LENGTH from django.utils.ipv6 import is_valid_ipv6_address from django.utils.regex_helper import _lazy_re_compile from django.utils.translation import gettext_lazy as _ @@ -155,7 +156,7 @@ class URLValidator(RegexValidator): message = _("Enter a valid URL.") schemes = ["http", "https", "ftp", "ftps"] unsafe_chars = frozenset("\t\r\n") - max_length = 2048 + max_length = MAX_URL_LENGTH def __init__(self, schemes=None, **kwargs): super().__init__(**kwargs) diff --git a/django/utils/html.py b/django/utils/html.py index ff8684f5a9..8892b9a740 100644 --- a/django/utils/html.py +++ b/django/utils/html.py @@ -11,7 +11,7 @@ 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 -from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS +from django.utils.http import MAX_URL_LENGTH, RFC3986_GENDELIMS, RFC3986_SUBDELIMS from django.utils.regex_helper import _lazy_re_compile from django.utils.safestring import SafeData, SafeString, mark_safe from django.utils.text import normalize_newlines @@ -39,7 +39,6 @@ VOID_ELEMENTS = frozenset( ) ) -MAX_URL_LENGTH = 2048 MAX_STRIP_TAGS_DEPTH = 50 diff --git a/django/utils/http.py b/django/utils/http.py index 78dfee7fee..87c2ac0d64 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -37,6 +37,7 @@ ASCTIME_DATE = _lazy_re_compile(r"^\w{3} %s %s %s %s$" % (__M, __D2, __T, __Y)) RFC3986_GENDELIMS = ":/?#[]@" RFC3986_SUBDELIMS = "!$&'()*+,;=" +MAX_URL_LENGTH = 2048 def urlencode(query, doseq=False): @@ -272,7 +273,10 @@ def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False): def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False): # Chrome considers any URL with more than two slashes to be absolute, but # urlparse is not so flexible. Treat any url with three slashes as unsafe. - if url.startswith("///"): + if url.startswith("///") or len(url) > MAX_URL_LENGTH: + # urlparse does not perform validation of inputs. Unicode normalization + # is very slow on Windows and can be a DoS attack vector. + # https://docs.python.org/3/library/urllib.parse.html#url-parsing-security return False try: url_info = urlparse(url) |
