Exempt SCRIPT_NAME from newly introduced --header-map treatment

This commit is contained in:
Paul J. Dorn 2024-04-24 08:48:27 +02:00
parent 77b65a0934
commit 01bcdb1d12
3 changed files with 22 additions and 9 deletions

View File

@ -1232,17 +1232,18 @@ the headers defined here can not be passed directly from the client.
**Command line:** ``--forwarded-allow-ips STRING``
**Default:** ``'127.0.0.1'``
**Default:** ``'127.0.0.1,::1'``
Front-end's IPs from which allowed to handle set secure headers.
(comma separate).
Set to ``*`` to disable checking of Front-end IPs (useful for setups
Set to ``*`` to disable checking of Front-end IPs. This is useful for setups
where you don't know in advance the IP address of Front-end, but
you still trust the environment).
instead have ensured via other means that none other than your
authorized Front-ends can access gunicorn.
By default, the value of the ``FORWARDED_ALLOW_IPS`` environment
variable. If it is not defined, the default is ``"127.0.0.1"``.
variable. If it is not defined, the default is ``"127.0.0.1,::1"``.
.. note::
@ -1498,6 +1499,9 @@ The value ``refuse`` will return an error if a request contains *any* such heade
The value ``dangerous`` matches the previous, not advisabble, behaviour of mapping different
header field names into the same environ name.
The (at this time, not configurable) header `SCRIPT_NAME` is permitted
without consulting this setting, if it is received from an allowed forwarder.
Use with care and only if necessary and after considering if your problem could
instead be solved by specifically renaming or rewriting only the intended headers
on a proxy in front of Gunicorn.

View File

@ -1263,17 +1263,18 @@ class ForwardedAllowIPS(Setting):
cli = ["--forwarded-allow-ips"]
meta = "STRING"
validator = validate_string_to_list
default = os.environ.get("FORWARDED_ALLOW_IPS", "127.0.0.1")
default = os.environ.get("FORWARDED_ALLOW_IPS", "127.0.0.1,::1")
desc = """\
Front-end's IPs from which allowed to handle set secure headers.
(comma separate).
Set to ``*`` to disable checking of Front-end IPs (useful for setups
Set to ``*`` to disable checking of Front-end IPs. This is useful for setups
where you don't know in advance the IP address of Front-end, but
you still trust the environment).
instead have ensured via other means that none other than your
authorized Front-ends can access gunicorn.
By default, the value of the ``FORWARDED_ALLOW_IPS`` environment
variable. If it is not defined, the default is ``"127.0.0.1"``.
variable. If it is not defined, the default is ``"127.0.0.1,::1"``.
.. note::
@ -2365,6 +2366,9 @@ class HeaderMap(Setting):
The value ``dangerous`` matches the previous, not advisabble, behaviour of mapping different
header field names into the same environ name.
The (at this time, not configurable) header `SCRIPT_NAME` is permitted
without consulting this setting, if it is received from an allowed forwarder.
Use with care and only if necessary and after considering if your problem could
instead be solved by specifically renaming or rewriting only the intended headers
on a proxy in front of Gunicorn.

View File

@ -78,6 +78,7 @@ class Message(object):
# handle scheme headers
scheme_header = False
secure_scheme_headers = {}
allowed_forwarder_headers = []
if from_trailer:
# nonsense. either a request is https from the beginning
# .. or we are just behind a proxy who does not remove conflicting trailers
@ -86,6 +87,7 @@ class Message(object):
not isinstance(self.peer_addr, tuple)
or self.peer_addr[0] in cfg.forwarded_allow_ips):
secure_scheme_headers = cfg.secure_scheme_headers
allowed_forwarder_headers = ["SCRIPT_NAME"]
# Parse headers into key/value pairs paying attention
# to continuation lines.
@ -144,7 +146,10 @@ class Message(object):
# HTTP_X_FORWARDED_FOR = 2001:db8::ha:cc:ed,127.0.0.1,::1
# Only modify after fixing *ALL* header transformations; network to wsgi env
if "_" in name:
if self.cfg.header_map == "dangerous":
if name in allowed_forwarder_headers:
# This forwarder may override our environment
pass
elif self.cfg.header_map == "dangerous":
# as if we did not know we cannot safely map this
pass
elif self.cfg.header_map == "drop":