While working on #258, we discovered that the url_has_allowed_host_and_scheme method does not use the urllib.parse module. Django copied the code to parse URLs( urlsplit, urlparse) from the urllib module, but version 4.1 does not include the logic to fix the vulnerability related to ASCII newlines and tabs in URLs(python/cpython#88048), even though it was already fixed in Python 3.11, so we decided to use the same approach we use in CL in the is_safe_url method.
OTOH, Django 4.2 includes a helper to fix the vulnerability, so we can refactor the is_safe_url method and remove the logic to prevent using garbage URLs (like empty ones or ones with spaces) and dangerous URLs (like JavaScript). The refactored function should look like this:
def is_safe_url(url: str, request: HttpRequest) -> bool:
sign_in_url = reverse("sign-in") in url
register_in_url = reverse("register") in url
not_safe_url = not url_has_allowed_host_and_scheme(
url,
allowed_hosts={request.get_host()},
require_https=request.is_secure(),
)
if any([sign_in_url, register_in_url, not_safe_url]):
return False
return True
While working on #258, we discovered that the url_has_allowed_host_and_scheme method does not use the urllib.parse module. Django copied the code to parse URLs( urlsplit, urlparse) from the urllib module, but version 4.1 does not include the logic to fix the vulnerability related to ASCII newlines and tabs in URLs(python/cpython#88048), even though it was already fixed in Python 3.11, so we decided to use the same approach we use in CL in the
is_safe_urlmethod.OTOH, Django 4.2 includes a helper to fix the vulnerability, so we can refactor the
is_safe_urlmethod and remove the logic to prevent using garbage URLs (like empty ones or ones with spaces) and dangerous URLs (like JavaScript). The refactored function should look like this: