fix: reject control characters in header field-value (RFC 9110 section 5.5)

field-vchar = VCHAR / obs-text; only SP and HTAB are permitted beyond
that. Previous validation only caught NUL/CR/LF, leaving BEL, DEL, FF,
and other C0/C1 controls accepted — a log/response injection risk. Now
rejected across the WSGI and ASGI Python parsers.
This commit is contained in:
Benoit Chesneau 2026-04-19 12:07:16 +02:00
parent 826bfc7e88
commit 2073e13dc8
2 changed files with 9 additions and 3 deletions

View File

@ -804,8 +804,11 @@ class PythonProtocol:
return True
def _has_invalid_header_chars(self, value):
"""Check for NUL, CR, LF in header value."""
return b'\x00' in value or b'\r' in value or b'\n' in value
"""RFC 9110 section 5.5: only VCHAR, SP, HTAB, and obs-text allowed."""
for c in value:
if c <= 0x08 or 0x0a <= c <= 0x1f or c == 0x7f:
return True
return False
class CallbackRequest:

View File

@ -130,7 +130,10 @@ TOKEN_RE = re.compile(r"[%s0-9a-zA-Z]+" % (re.escape(RFC9110_5_6_2_TOKEN_SPECIAL
METHOD_BADCHAR_RE = re.compile("[a-z#]")
# usually 1.0 or 1.1 - RFC9112 permits restricting to single-digit versions
VERSION_RE = re.compile(r"HTTP/(\d)\.(\d)")
RFC9110_5_5_INVALID_AND_DANGEROUS = re.compile(r"[\0\r\n]")
# RFC 9110 section 5.5: field-vchar = VCHAR / obs-text; SP and HTAB are the
# only non-VCHAR bytes allowed in a field-value. Anything else in the
# control range (0x00-0x1F except HTAB, plus DEL 0x7F) must be rejected.
RFC9110_5_5_INVALID_AND_DANGEROUS = re.compile(r"[\x00-\x08\x0a-\x1f\x7f]")
# RFC 9110 section 6.5.1: fields forbidden in trailers because they alter
# routing, framing, or authentication. Using the uppercased names stored