diff --git a/CHANGES.rst b/CHANGES.rst index 0a328dda8..b82802002 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,9 @@ Unreleased matching. In ``bind_to_environ``, the ``server_name`` parameter is not used if ``host_matching`` is enabled. If ``default_subdomain`` is set, it is used if a subdomain could not be determined. :issue:`3005` +- If a request object is passed to ``Map.bind_to_environ``, the host is + validated against ``request.trusted_hosts``. An invalid host will raise a + 400 error. :issue:`3007` Version 3.1.3 diff --git a/src/werkzeug/routing/map.py b/src/werkzeug/routing/map.py index de488f3af..8293f3f74 100644 --- a/src/werkzeug/routing/map.py +++ b/src/werkzeug/routing/map.py @@ -8,7 +8,6 @@ from urllib.parse import urljoin from urllib.parse import urlunsplit -from .._internal import _get_environ from .._internal import _wsgi_decoding_dance from ..datastructures import ImmutableDict from ..datastructures import MultiDict @@ -16,6 +15,7 @@ from ..exceptions import HTTPException from ..exceptions import MethodNotAllowed from ..exceptions import NotFound +from ..sansio.request import Request as SansIORequest from ..urls import _urlencode from ..wsgi import get_host from .converters import DEFAULT_CONVERTERS @@ -278,7 +278,9 @@ def bind_to_environ( ``""`` is used. :param environ: The WSGI environ for the request. Can also be a - ``Request`` with an ``environ`` attribute. + ``Request`` with an ``environ`` attribute; in that case, its + :attr:`~.Request.host` is accessed to validate its + :attr:`~.Request.trusted_hosts`. :param server_name: When subdomain matching is enabled and ``subdomain`` is not given, the subdomain is determined by removing this ``host:port`` as a suffix from the request's ``Host``. If the scheme @@ -298,6 +300,10 @@ def bind_to_environ( .. versionchanged:: 3.2 ``server_name`` is ignored if ``host_matching`` is enabled. + .. versionchanged:: 3.2 + If the ``environ`` argument is a ``Request``, access ``request.host`` + to validate``request.trusted_hosts``. + .. versionchanged:: 1.0.0 If ``server_name`` specifies port 443, it will match if the scheme is ``https`` and ``Host`` does not specify a port. @@ -312,8 +318,13 @@ def bind_to_environ( .. versionchanged:: 0.5 Removed the ``calculate_subdomain`` parameter which was not used. """ - env = _get_environ(environ) - wsgi_server_name = get_host(env).lower() + if isinstance(environ, SansIORequest): + env = environ.environ + wsgi_server_name = environ.host.lower() + else: + env = environ + wsgi_server_name = get_host(env).lower() + scheme = env["wsgi.url_scheme"] upgrade = any( v.strip() == "upgrade"