libwww-perl / libwww-perl/HTTP-Daemon
Content_Length is silently aliased to Content-Length on incoming requests
Nobody has claimed this yet.
- Dominant language
- Perl
- Stars
- 6
- Forks
- 17
- PR merge metrics
- No merged PRs in 30d
Description
Split out from #56 / CVE-2022-31081 (POC #5).
Content_Length and Content-Length are syntactically distinct header field names. Per RFC 9110 §5.1, field-name = token; per RFC 9110 §5.6.2, tchar includes both _ and -, so both names are valid tokens. Field names are case-insensitive per RFC 9110 §5.1, but case-insensitivity does not extend to _ vs - — these are simply different fields.
$HTTP::Headers::TRANSLATE_UNDERSCORE defaults to 1, so an incoming Content_Length: 3 is stored as Content-Length: 3. The fat-comma ergonomics this enables are useful for outgoing message construction, but on the server side it conflates two distinct fields.
The multi-value mismatch case (Content_Length: 3 + Content-Length: 22) is now caught by the CVE-2022-31081 fix at lib/HTTP/Daemon.pm:296-315, since the joined 3, 22 fails the "all values equal" check and returns 400.
Security relevance — still real
A request with Content_Length: N alone (no Content-Length) frames as zero-body for a strict proxy that treats underscored headers as non-standard (e.g. nginx's default underscores_in_headers off), but as N bytes for HTTP::Daemon — a CL.0 desync. Risk exists against any proxy that forwards underscored headers verbatim.
Proposed fix
@vanHoesel suggested in #56 adding an HTTP::Daemon constructor option underscores_in_headers / drop_underscores that filters underscored header names before they reach HTTP::Headers::push_header.
Default value (strip vs. translate) is the contentious bit — defaulting to strip is safer but breaks any user relying on the alias. A middle option: leave HTTP::Headers behavior unchanged but have HTTP::Daemon strip underscored header names from incoming requests by default, since the daemon is the server-side surface where the smuggling risk lives.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading lib/HTTP/Daemon.pm:296-315 and tracing incoming headers into HTTP::Headers::push_header, then review the context in #56 and CVE-2022-31081. The maintainer decision is whether HTTP::Daemon should strip underscored incoming headers by default or expose an option; done means the chosen behavior prevents the described framing mismatch without an unreviewed compatibility change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- perl
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100