Repository navigation
Conversation
Validate Content-Length as 1*DIGIT inside HttpRequestImpl::addHeader, the single place byte-level request headers enter the message: * An empty value, a numeric prefix such as "10x", or a value beyond the size_t range is invalid framing (RFC 9110 section 8.6). Previously an empty value was indistinguishable from an absent header, so the bytes after the header section were parsed as the next request. * A repeated Content-Length whose value differs from the one already received is rejected instead of silently keeping the first one (RFC 9112 section 6.3), closing a CL.CL request smuggling vector. * A header line with whitespace between the field name and the colon is rejected with 400, as required by RFC 9112 section 5.1. The parsed value is cached in contentLengthHeaderValue_, so the parser no longer carries its own copy of the digit scan. Fixes drogonframework#2648
Contributor
Author
|
The This is an environment change on the runner image, not a regression from this PR:
No changes in this PR touch trantor, CMake configuration, or the dependency setup. It should go green once the trantor submodule is updated for OpenSSL 4.1, or once the macOS CI job pins |
The request parser needs the same 1*DIGIT validation, so share one implementation instead of keeping separate copies that can diverge.
Picks up the OpenSSL 4.x build fixes (an-tao/trantor#423, drogonframework#422), which the macOS 15 CI needs because Homebrew now ships OpenSSL 4.1.
The first field already caches its parsed length in contentLengthHeaderValue_, so compare against that instead of scanning the stored string again for every repeated field.
Contributor
Author
|
Superseded by #2665, which combines the request and response framing fixes on top of current master. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2648. Follow-up to #2646, which made the
Content-Lengthdigit scan strict but left three ways for request framing to stay ambiguous.The
Content-Lengthvalue is now validated insideHttpRequestImpl::addHeader, the single place byte-level request headers enter the message:Content-Length:trimmed to an empty string and was indistinguishable from an absent header, so everything after the header section was parsed as the next request. It is now rejected (RFC 9110 §8.6,Content-Length = 1*DIGIT).headers_.emplacesilently kept the first one, soContent-Length: 0followed byContent-Length: 100framed the body as zero bytes (CL.CL desync). A differing repeat is now rejected; identical repeats are still accepted (RFC 9112 §6.3).Content-Length : 10produced the field name"content-length ", which matched nothing and was dropped entirely. The parser now rejects such a line with 400, as RFC 9112 §5.1 requires.Because
addHeaderalready returns the validated value, it is cached incontentLengthHeaderValue_and the parser's duplicate digit scan is removed.Comma-separated lists (
Content-Length: 42, 42) are rejected. RFC 9112 §6.3 permits folding identical members but does not require it; rejecting every list is simpler while remaining compliant.Test plan
lib/tests/integration_test/client/ContentLengthFramingTest.cc:size_t→ 400IsValidHeader,IsValidCookie): pass.RejectInvalidContentLength(10x→ 400) from fix: validate Content-Length as complete decimal #2646 still passes.The response side still uses
std::stoullinHttpResponseParserand accepts numeric prefixes; that is out of scope here and noted in #2648.