Skip to content

Commit

Permalink
fix: cr
Browse files Browse the repository at this point in the history
  • Loading branch information
nannan00 committed Feb 29, 2024
1 parent 1b8818f commit 05676d8
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions src/bk-login/bklogin/authentication/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
specific language governing permissions and limitations under the License.
"""
import unicodedata
from typing import Set
from urllib.parse import urlparse

from django.http.request import split_domain_port, validate_host


# Copied from django.utils.http.url_has_allowed_host_and_scheme()
def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
def url_has_allowed_host_and_scheme(
url: str | None, allowed_hosts: Set | str | None, require_https: bool = False
) -> bool:
"""
Return ``True`` if the url uses an allowed host and a safe scheme.
Expand All @@ -30,12 +33,15 @@ def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
"""
if url is not None:
url = url.strip()

if not url:
return False

if allowed_hosts is None:
allowed_hosts = set()
elif isinstance(allowed_hosts, str):
allowed_hosts = {allowed_hosts}

# Chrome treats \ completely as / in paths but it could be part of some
# basic auth credentials so we need to check both URLs.
return _url_has_allowed_host_and_scheme(
Expand All @@ -50,7 +56,7 @@ def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
# (2) 泛域名匹配,比如 .example.com 可匹配 foo.example.com、example.com、foo.example.com:8000、example.com:8080
# (3) 精确域名匹配,比如 example.com 可匹配 example.com、example.com:8000
# (4) 精确域名&端口匹配,比如 example.com:9000 只可匹配 example.com:9000
def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
def _url_has_allowed_host_and_scheme(url: str, allowed_hosts: Set, require_https: bool = 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("///"):
Expand All @@ -59,24 +65,26 @@ def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
url_info = urlparse(url)
except ValueError: # e.g. invalid IPv6 addresses
return False

# Forbid URLs like http:///example.com - with a scheme, but without a hostname.
# In that URL, example.com is not the hostname but, a path component. However,
# Chrome will still consider example.com to be the hostname, so we must not
# allow this syntax.
if not url_info.netloc and url_info.scheme:
return False

# Forbid URLs that start with control characters. Some browsers (like
# Chrome) ignore quite a few control characters at the start of a
# URL and might consider the URL as scheme relative.
if unicodedata.category(url[0])[0] == "C":
return False

# Check if the scheme is valid.
scheme = url_info.scheme
# Consider URLs without a scheme (e.g. //example.com/p) to be http.
if not url_info.scheme and url_info.netloc:
scheme = "http"
valid_schemes = ["https"] if require_https else ["http", "https"]

# Check if the scheme is valid.
if scheme and scheme not in valid_schemes:
return False

Expand Down

0 comments on commit 05676d8

Please sign in to comment.