You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Review which characters should be trimmed for cookie and header data #1084
By default, the PHP native [lr]trim() functions, trim ASCII whitespace and the NUL byte character.
PHP 8.6 changes the default value of the $characters parameter to also include the form feed - "\f" - character, which was previously not trimmed.
⚠️Keep in mind that [lr]trim() only operates on the leading and/or trailing characters for a text string. It does not affect the characters in the "middle" !
Requests uses [lr]trim() in various places throughout the codebase.
To make this code PHP cross-version compatible, PR #1083 made the following changes:
Introduced two class constants to represent the different default values for the $characters parameter.
Made the $characters being trimmed explicit in each of the [lr]trim() function calls (if it wasn't already).
To determine which characters should be trimmed, the following rule of thumb has been used for the initial changes made in PR #1083: "Use the PHP 8.6 default (Trim::WHITESPACE_CHARS), except when the trimming may be subject to an RFC or other documented rules, in which case use the PHP < 8.6 default (Trim::WHITESPACE_CHARS_NO_FF)"
That way, we preserved existing behaviour in "important" places, while benefitting from the new default value everywhere else.
Task
For all calls to [lr]trim() which currently use the Trim::WHITESPACE_CHARS_NO_FF value for $characters, it should be researched whether that is correct by checking RFCs and other applicable rules. In some cases, it may also be prudent to evaluate how other projects similar to Requests, like for instance Guzzle, handle these text strings.
If the trimming is correct, it should be documented that this was verified via a comment in this issue.
If a change is necessary, please submit a PR and include tests safeguarding the change to the value passed for $characters.
After PR #1083, there will be 14 places in the codebase where this review task is necessary.
I reviewed all 14 Trim::WHITESPACE_CHARS_NO_FF call sites against the protocol rules, using the current #1083 head (6d9e4192f6714c652ae80cb71f590d6073234b9). For the PHP 8.6 compatibility question in this issue, I do not think any of these sites should start trimming form feed (\f).
HTTP response/header parsing
src/Requests.php (header value) and src/Transport/Curl.php (raw response headers): RFC 9110 §5.6.3 defines OWS/BWS as only SP / HTAB; form feed is not HTTP whitespace. RFC 9110 §5.5 also excludes leading/trailing whitespace from the field value after parsing. So preserving the pre-8.6 character set is preferable to silently accepting/trimming \f.
The three calls in Requests::decode_chunked() should also keep \f significant. RFC 9112 §7.1 defines chunk-size = 1*HEXDIG, chunk framing with exact CRLF, and chunk-extension BWS via HTTP BWS (SP/HTAB). Form feed is not permitted framing whitespace and should not be normalized away.
One of the trims (trim($matches[1], ...)) is effectively redundant because the regexp captures only hex digits, but changing that is outside the PHP 8.6 compatibility scope.
Compressed response bodies
The checks in Requests::decompress() and Requests::compatible_gzinflate() operate on binary entity data. There is no protocol rule under which a form-feed octet makes a binary body "empty". Keeping \f out of the trim set avoids reclassifying a non-empty binary payload as empty/false.
TLS subjectAltName parsing
The two Ssl::verify_certificate() trims process OpenSSL's textual rendering of subjectAltName. RFC 5280 defines dNSName as IA5String using the preferred DNS name syntax; form feed is not valid DNS-name whitespace. It therefore should not be silently stripped from the name.
The five calls in Cookie::parse() should not add form feed either. RFC 6265 §5.2 explicitly says to remove leading/trailing WSP from the cookie name/value, where WSP is SP/HTAB. Attribute parsing similarly does not define form feed as ignorable whitespace. This is a particularly strong reason to keep WHITESPACE_CHARS_NO_FF for the PHP 8.6 compatibility change.
This review only answers the issue's PHP 8.6 question: should \f newly become trimmable at these 14 call sites? My conclusion is no for all 14.
There is a separate possible hardening/standards-cleanup question: some of the current calls trim more than the protocol-defined SP/HTAB (for example CR/LF/VT/NUL via PHP's historical default). Tightening those sets could change long-standing permissive behavior and should be evaluated separately with dedicated compatibility tests rather than folded into #1083.
I reviewed all 14 Trim::WHITESPACE_CHARS_NO_FF call sites against the protocol rules, using the current #1083 head (6d9e4192f6714c652ae80cb71f590d6073234b9).
<snip>
Scope note
This review only answers the issue's PHP 8.6 question: should \f newly become trimmable at these 14 call sites? My conclusion is no for all 14.
There is a separate possible hardening/standards-cleanup question: some of the current calls trim more than the protocol-defined SP/HTAB (for example CR/LF/VT/NUL via PHP's historical default). Tightening those sets could change long-standing permissive behavior and should be evaluated separately with dedicated compatibility tests rather than folded into #1083.
@asllanmaciel Thank you for starting this review and for including links to all the sources you base your conclusions on. This helps a lot!
The scope of this issue is not limited to the PHP 8.6 change, so the "separate possible hardening/standards-cleanup question"is the task and based on your analysis, it reads to me that some changes may be warranted as a follow up to PR #1083(which should have been merged after the approval, not sure why that didn't happen - will merge now to make it more straight-forward to start work on the follow-up).
Would you be willing to create such a follow-up PR (including adding tests to safeguard the hardening) ?
I imagine adding additional WHITESPACE_CHARS_RFC### constants in the new Trim class would be a good way to document the specifications and ensure the right set of characters is used in various places.
I also imagine that where form feed (or specific other) whitespace isn't allowed at all, it may be a reason not to accept the input by throwing an exception instead of trimming ?
How does that sound to you ?
For the record for anyone who comes across this issue and is wondering what the abbreviations mean:
The following core rules are included by reference, as defined in Appendix B.1 of [RFC5234]: ALPHA (letters), CR (carriage return), CRLF (CR LF), CTL (controls), DIGIT (decimal 0-9), DQUOTE (double quote), HEXDIG (hexadecimal 0-9/A-F/a-f), HTAB (horizontal tab), LF (line feed), OCTET (any 8-bit sequence of data), SP (space), and VCHAR (any visible US-ASCII character).
One update to the Cookie analysis: RFC 6265 has now been obsoleted by RFC 10025 (Cookies: HTTP State Management Mechanism, July 2026), so the Cookie-related review should probably use RFC 10025 as the primary reference.
The conclusion about whitespace remains the same, but RFC 10025 also clarifies the handling of control characters.
In the Set-Cookie parsing algorithm (Section 5.6), a user agent rejects the entire set-cookie-string if it contains:
%x00-08 / %x0A-1F / %x7F
HTAB (%x09) is excluded because it is handled as whitespace.
After that validation, leading and trailing WSP are removed from cookie names/values and attribute names/values:
WSP=SP/HTAB
This means form feed (%x0C) should not merely be left untrimmed: it is a disallowed control character and should cause the Set-Cookie input to be rejected.
So RFC 10025 appears to support separating two responsibilities:
validation:
reject CTLs other than HTAB
normalization:
trim SP / HTAB where WSP is allowed
A follow-up PR may therefore need to consider explicit CTL validation as well as narrowing the trimming character set.
RFC 10025 also defines the server-side Set-Cookie grammar using HTTP BWS and OWS, which further supports keeping protocol-specific whitespace rules separate from PHP's native trim() defaults.
Activity
asllanmaciel commentedon Sep 16, 2026
I reviewed all 14
Trim::WHITESPACE_CHARS_NO_FFcall sites against the protocol rules, using the current #1083 head (6d9e4192f6714c652ae80cb71f590d6073234b9). For the PHP 8.6 compatibility question in this issue, I do not think any of these sites should start trimming form feed (\f).HTTP response/header parsing
src/Requests.php(header value) andsrc/Transport/Curl.php(raw response headers): RFC 9110 §5.6.3 defines OWS/BWS as onlySP / HTAB; form feed is not HTTP whitespace. RFC 9110 §5.5 also excludes leading/trailing whitespace from the field value after parsing. So preserving the pre-8.6 character set is preferable to silently accepting/trimming\f.Reference: https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.3
Chunked transfer decoding
The three calls in
Requests::decode_chunked()should also keep\fsignificant. RFC 9112 §7.1 defineschunk-size = 1*HEXDIG, chunk framing with exact CRLF, and chunk-extension BWS via HTTP BWS (SP/HTAB). Form feed is not permitted framing whitespace and should not be normalized away.Reference: https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1
One of the trims (
trim($matches[1], ...)) is effectively redundant because the regexp captures only hex digits, but changing that is outside the PHP 8.6 compatibility scope.Compressed response bodies
The checks in
Requests::decompress()andRequests::compatible_gzinflate()operate on binary entity data. There is no protocol rule under which a form-feed octet makes a binary body "empty". Keeping\fout of the trim set avoids reclassifying a non-empty binary payload as empty/false.TLS subjectAltName parsing
The two
Ssl::verify_certificate()trims process OpenSSL's textual rendering ofsubjectAltName. RFC 5280 definesdNSNameas IA5String using the preferred DNS name syntax; form feed is not valid DNS-name whitespace. It therefore should not be silently stripped from the name.Reference: https://www.rfc-editor.org/rfc/rfc5280.html#section-4.2.1.6
Cookie parsing
The five calls in
Cookie::parse()should not add form feed either. RFC 6265 §5.2 explicitly says to remove leading/trailing WSP from the cookie name/value, where WSP is SP/HTAB. Attribute parsing similarly does not define form feed as ignorable whitespace. This is a particularly strong reason to keepWHITESPACE_CHARS_NO_FFfor the PHP 8.6 compatibility change.Reference: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.2
Scope note
This review only answers the issue's PHP 8.6 question: should
\fnewly become trimmable at these 14 call sites? My conclusion is no for all 14.There is a separate possible hardening/standards-cleanup question: some of the current calls trim more than the protocol-defined SP/HTAB (for example CR/LF/VT/NUL via PHP's historical default). Tightening those sets could change long-standing permissive behavior and should be evaluated separately with dedicated compatibility tests rather than folded into #1083.
jrfnl commentedon Sep 16, 2026
@asllanmaciel Thank you for starting this review and for including links to all the sources you base your conclusions on. This helps a lot!
The scope of this issue is not limited to the PHP 8.6 change, so the "separate possible hardening/standards-cleanup question" is the task and based on your analysis, it reads to me that some changes may be warranted as a follow up to PR #1083 (which should have been merged after the approval, not sure why that didn't happen - will merge now to make it more straight-forward to start work on the follow-up).
Would you be willing to create such a follow-up PR (including adding tests to safeguard the hardening) ?
I imagine adding additional
WHITESPACE_CHARS_RFC###constants in the newTrimclass would be a good way to document the specifications and ensure the right set of characters is used in various places.I also imagine that where form feed (or specific other) whitespace isn't allowed at all, it may be a reason not to accept the input by throwing an exception instead of trimming ?
How does that sound to you ?
For the record for anyone who comes across this issue and is wondering what the abbreviations mean:
masakielastic commentedon Sep 17, 2026
One update to the Cookie analysis: RFC 6265 has now been obsoleted by RFC 10025 (Cookies: HTTP State Management Mechanism, July 2026), so the Cookie-related review should probably use RFC 10025 as the primary reference.
The conclusion about whitespace remains the same, but RFC 10025 also clarifies the handling of control characters.
In the Set-Cookie parsing algorithm (Section 5.6), a user agent rejects the entire
set-cookie-stringif it contains:HTAB (
%x09) is excluded because it is handled as whitespace.After that validation, leading and trailing
WSPare removed from cookie names/values and attribute names/values:This means form feed (
%x0C) should not merely be left untrimmed: it is a disallowed control character and should cause the Set-Cookie input to be rejected.So RFC 10025 appears to support separating two responsibilities:
A follow-up PR may therefore need to consider explicit CTL validation as well as narrowing the trimming character set.
RFC 10025 also defines the server-side
Set-Cookiegrammar using HTTPBWSandOWS, which further supports keeping protocol-specific whitespace rules separate from PHP's nativetrim()defaults.