{"id":"b89494c0d9bf600f","repo":"psf/requests","slug":"invalid-leading-whitespace-reserved-character-s","errorCode":null,"errorMessage":"Invalid leading whitespace, reserved character(s), or return character(s) in header {header_kind}: {header_part!r}","messagePattern":"Invalid leading whitespace, reserved character\\(s\\), or return character\\(s\\) in header (.+?): (.+?)","errorType":"validation","errorClass":"InvalidHeader","httpStatus":null,"severity":"error","filePath":"src/requests/utils.py","lineNumber":1116,"sourceCode":"def _validate_header_part(\n    header: tuple[str | bytes, str | bytes],\n    header_part: str | bytes,\n    header_validator_index: int,\n) -> None:\n    if isinstance(header_part, str):\n        validator = _HEADER_VALIDATORS_STR[header_validator_index]\n    elif isinstance(header_part, bytes):\n        # runtime guard for non-str/bytes input\n        validator = _HEADER_VALIDATORS_BYTE[header_validator_index]\n    else:\n        raise InvalidHeader(\n            f\"Header part ({header_part!r}) from {header} \"\n            f\"must be of type str or bytes, not {type(header_part)}\"\n        )\n\n    if not validator.match(header_part):  # type: ignore[arg-type]\n        header_kind = \"name\" if header_validator_index == 0 else \"value\"\n        raise InvalidHeader(\n            f\"Invalid leading whitespace, reserved character(s), or return \"\n            f\"character(s) in header {header_kind}: {header_part!r}\"\n        )\n\n\ndef urldefragauth(url: str) -> str:\n    \"\"\"\n    Given a url remove the fragment and the authentication part.\n\n    :rtype: str\n    \"\"\"\n    scheme, netloc, path, params, query, _fragment = urlparse(url)\n\n    # see func:`prepend_scheme_if_needed`\n    if not netloc:\n        netloc, path = path, netloc\n\n    netloc = netloc.rsplit(\"@\", 1)[-1]","sourceCodeStart":1098,"sourceCodeEnd":1134,"githubUrl":"https://github.com/psf/requests/blob/414f0513c33883adf6f2b46901d4f0b38a455851/src/requests/utils.py#L1098-L1134","documentation":"Raised as `requests.exceptions.InvalidHeader` from `_validate_header_part()` in `src/requests/utils.py:1116` when a header name or value fails the `_HEADER_VALIDATORS_STR`/`_HEADER_VALIDATORS_BYTE` regex. These validators reject leading whitespace and CR/LF (return) characters in values, and reserved/illegal characters in names. This is primarily a security control against HTTP header injection (request smuggling / response splitting via embedded '\\r\\n'), added after CVE-2022-32213-class issues across HTTP clients.","triggerScenarios":"Any request where a header value contains '\\r' or '\\n' (e.g. `headers={'X-Note': 'line1\\nline2'}`), starts with a space or tab, or where a header name contains characters outside the RFC 7230 token set (spaces, colons, non-ASCII). The message's `header_kind` tells you whether the name or the value failed.","commonSituations":"Header values read from files or env vars that carry a trailing/embedded newline (e.g. `open('token.txt').read()` without `.strip()`); user input interpolated into headers (injection attempt or accident); multi-line strings from YAML config; copy-pasted tokens with leading whitespace; header names with a stray trailing colon like 'Authorization:'.","solutions":["Strip the value: `headers={'Authorization': token.strip()}` — newlines from `read()` or env vars are the most common cause.","Never place raw user input into headers; sanitize or reject values containing '\\r' or '\\n'.","Remove the colon or spaces from the header name — pass 'Authorization', not 'Authorization:'.","If the value is legitimately multi-line, it cannot be a single HTTP header; restructure (e.g. base64-encode it)."],"exampleFix":"# before\ntoken = open('token.txt').read()  # ends with '\\n'\nrequests.get(url, headers={'Authorization': f'Bearer {token}'})\n# after\ntoken = open('token.txt').read().strip()\nrequests.get(url, headers={'Authorization': f'Bearer {token}'})","handlingStrategy":"validation","validationCode":"import re\n_INVALID = re.compile(r'^\\s|[\\r\\n]')\ndef header_value_is_safe(value):\n    s = value.decode('latin-1') if isinstance(value, bytes) else value\n    return not _INVALID.search(s)\n\nassert all(header_value_is_safe(v) for v in headers.values()), 'header contains leading whitespace or CR/LF'","typeGuard":null,"tryCatchPattern":"try:\n    resp = requests.get(url, headers=headers)\nexcept requests.exceptions.InvalidHeader as e:\n    # leading whitespace or CR/LF in a header — often an injection attempt\n    log.warning('Rejected unsafe header: %s', e)","preventionTips":["Strip whitespace from header values built from user input (value.strip())","Reject or sanitize CR/LF in any user-controlled value destined for a header — this check is your defense against header injection, don't work around it","Validate header names against RFC 7230 token characters at the trust boundary"],"tags":["headers","security","header-injection","validation","python","requests"],"analyzedSha":"414f0513c33883adf6f2b46901d4f0b38a455851","analyzedAt":"2026-07-31T19:24:57.696Z","schemaVersion":2}