fix: reject forbidden trailer field-names (RFC 9110 section 6.5.1)

Host, Content-Length, Transfer-Encoding, Trailer, Authorization, and TE
are not allowed in trailer sections; accepting them enables smuggling
and routing confusion. Both WSGI and ASGI Python parsers now raise
InvalidHeaderName when any of these appears in a trailer.
This commit is contained in:
Benoit Chesneau 2026-04-19 11:41:00 +02:00
parent 3b3752eb90
commit a9270e3f9a
2 changed files with 36 additions and 0 deletions

View File

@ -29,6 +29,18 @@ class InvalidProxyHeader(ParseError):
PP_V2_SIGNATURE = b"\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
# RFC 9110 section 6.5.1: fields forbidden in trailers because they alter
# routing, framing, or authentication.
RFC9110_6_5_1_FORBIDDEN_TRAILER = frozenset((
b"host",
b"content-length",
b"transfer-encoding",
b"trailer",
b"authorization",
b"te",
))
class PPCommand(IntEnum):
"""PROXY protocol v2 commands."""
LOCAL = 0x0
@ -756,6 +768,14 @@ class PythonProtocol:
self._on_message_complete()
return True
# RFC 9110 section 6.5.1: reject fields that must not appear
# in trailers.
colon = line.find(b':')
if colon > 0:
name = line[:colon].strip(b' \t').lower()
if name in RFC9110_6_5_1_FORBIDDEN_TRAILER:
raise InvalidHeaderName(name.decode('latin-1'))
return False
def _is_valid_method(self, method):

View File

@ -132,6 +132,18 @@ METHOD_BADCHAR_RE = re.compile("[a-z#]")
VERSION_RE = re.compile(r"HTTP/(\d)\.(\d)")
RFC9110_5_5_INVALID_AND_DANGEROUS = re.compile(r"[\0\r\n]")
# RFC 9110 section 6.5.1: fields forbidden in trailers because they alter
# routing, framing, or authentication. Using the uppercased names stored
# by parse_headers.
RFC9110_6_5_1_FORBIDDEN_TRAILER = frozenset((
"HOST",
"CONTENT-LENGTH",
"TRANSFER-ENCODING",
"TRAILER",
"AUTHORIZATION",
"TE",
))
def _ip_in_allow_list(ip_str, allow_list, networks):
"""Check if IP address is in the allow list.
@ -235,6 +247,10 @@ class Message:
# b"\xDF".decode("latin-1").upper().encode("ascii") == b"SS"
name = name.upper()
# RFC 9110 section 6.5.1
if from_trailer and name in RFC9110_6_5_1_FORBIDDEN_TRAILER:
raise InvalidHeaderName(name)
value = [value.strip(" \t")]
# Consume value continuation lines..