Added check for pseudo-headers in trailers#13603
Conversation
Motivation: According to the RFC for HTTP2 on Section 8.1.2.1, 'Pseudo-header fields MUST NOT appear in trailers. Endpoints MUST treat a request or response that contains undefined or invalid pseudo-header fields as malformed (Section 8.1.2.6).' Modifications: Updated Http2Decoder to check trailers for Pseudo-Headers and treat them as invalid requests according to RFC 7540 Section 8.1.2.6 Result: After this change, requests with Pseudo-Headers sent inside trailers will be treated as malformed and a stream error is thrown
|
@isaacrivriv did you sign our icla ? https://netty.io/s/icla ? |
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Outdated
Show resolved
Hide resolved
|
Yes it should have been signed already! I followed the steps in the developer guide and signed it before pushing the PR |
Co-authored-by: Norman Maurer <norman_maurer@apple.com>
bryce-anderson
left a comment
There was a problem hiding this comment.
A few small suggestions but otherwise looks good!
codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java
Outdated
Show resolved
Hide resolved
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Show resolved
Hide resolved
There was a problem hiding this comment.
The (old) RFC 7540 has:
Pseudo-header fields defined for requests MUST NOT appear
in responses; pseudo-header fields defined for responses MUST NOT
appear in requests. Pseudo-header fields MUST NOT appear in
trailers.
Where are we doing that first part? I'd expect to see the mirror of this logic elsewhere. Do we just not have that logic anywhere?
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Outdated
Show resolved
Hide resolved
|
@isaacrivriv please let us know once this is ready for review again |
|
Sorry for the delay, got back to this again this week. I'm not seeing code where Netty validates that sending pseudo-headers in a request/response. I created issue #13646 to follow up. I tried a quick test locally to add code to verify but a lot of the tests started failing. Will verify this but in the mean time I will push the clean up comments for this specific issue |
a56dc1f to
7396915
Compare
|
Should be ready for review, tagged you all when you get a chance. Thanks! |
7396915 to
d2a175d
Compare
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Outdated
Show resolved
Hide resolved
As suggested, removed unused import, used iterator instead of header.names(), updated header name in tests for case where `randomString` can generate a string with a colon at the start, and updated comments to match newer RFC Co-authored-by: Bryce Anderson <bryce_anderson@apple.com>
d2a175d to
8ecc840
Compare
|
Should be ready for review again |
|
@vietj PTAL as well |
| } else { | ||
| // Need to check trailers don't contain pseudo headers. According to RFC 9113 | ||
| // Trailers MUST NOT include pseudo-header fields (Section 8.3). | ||
| if (!headers.isEmpty()) { | ||
| for (Iterator<Entry<CharSequence, CharSequence>> iterator = | ||
| headers.iterator(); iterator.hasNext();) { | ||
| if (Http2Headers.PseudoHeaderName.hasPseudoHeaderFormat(iterator.next().getKey())) { | ||
| throw streamError(stream.id(), PROTOCOL_ERROR, | ||
| "Found invalid Pseudo-Header in trailers"); | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
| } else { | |
| // Need to check trailers don't contain pseudo headers. According to RFC 9113 | |
| // Trailers MUST NOT include pseudo-header fields (Section 8.3). | |
| if (!headers.isEmpty()) { | |
| for (Iterator<Entry<CharSequence, CharSequence>> iterator = | |
| headers.iterator(); iterator.hasNext();) { | |
| if (Http2Headers.PseudoHeaderName.hasPseudoHeaderFormat(iterator.next().getKey())) { | |
| throw streamError(stream.id(), PROTOCOL_ERROR, | |
| "Found invalid Pseudo-Header in trailers"); | |
| } | |
| } | |
| } | |
| } | |
| } else if (!headers.isEmpty()) { | |
| // Need to check trailers don't contain pseudo headers. According to RFC 9113 | |
| // Trailers MUST NOT include pseudo-header fields (Section 8.3). | |
| for (Iterator<Entry<CharSequence, CharSequence>> iterator = | |
| headers.iterator(); iterator.hasNext();) { | |
| if (Http2Headers.PseudoHeaderName.hasPseudoHeaderFormat(iterator.next().getKey())) { | |
| throw streamError(stream.id(), PROTOCOL_ERROR, | |
| "Found invalid Pseudo-Header in trailers"); | |
| } | |
| } | |
| } |
|
I cannot see any test that triggers the bug that is fixed here, only existing test modifications that do not affect it |
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Outdated
Show resolved
Hide resolved
...-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2ConnectionHandlerBuilder.java
Outdated
Show resolved
Hide resolved
18f2f5a to
4d85799
Compare
connection decoder for verifying trailer headers.
4d85799 to
4fe3207
Compare
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Outdated
Show resolved
Hide resolved
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Outdated
Show resolved
Hide resolved
|
I did some cleanup and added a test case /cc @vietj |
idelpivnitskiy
left a comment
There was a problem hiding this comment.
Thanks for the contribution!
One minor suggestion:
codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionDecoder.java
Outdated
Show resolved
Hide resolved
|
@isaacrivriv thanks a lot! |
Motivation: According to the RFC for HTTP2 on Section 8.1.2.1, 'Pseudo-header fields MUST NOT appear in trailers. Endpoints MUST treat a request or response that contains undefined or invalid pseudo-header fields as malformed (Section 8.1.2.6).' Modifications: Updated Http2Decoder to check trailers for Pseudo-Headers and treat them as invalid requests according to RFC 7540 Section 8.1.2.6 Result: After this change, requests with Pseudo-Headers sent inside trailers will be treated as malformed and a stream error is thrown. Fixes: #13602 --------- Co-authored-by: Norman Maurer <norman_maurer@apple.com> Co-authored-by: Bryce Anderson <bryce_anderson@apple.com>
| "Multiple content-length headers received"); | ||
| } | ||
| } | ||
| } else if (validateHeaders && !headers.isEmpty()) { |
There was a problem hiding this comment.
This change broke users of grpc-netty.
This is clearly a grpc-netty bug so there's no action required in Netty - I just wanted to comment here to make the maintainers aware of this issue.
| // Need to check trailers don't contain pseudo headers. According to RFC 9113 | ||
| // Trailers MUST NOT include pseudo-header fields (Section 8.3). | ||
| for (Iterator<Entry<CharSequence, CharSequence>> iterator = | ||
| headers.iterator(); iterator.hasNext();) { |
There was a problem hiding this comment.
@ejona86 @pkoenig10 The usage of isEmpty was fixed in grpc/grpc-java#10663 and #13717, but we did not look closely enough at the problem, because on this line we also call the iterator() method on the Http2Headers, which AbstractHttp2Headers still does not implement: https://github.com/grpc/grpc-java/blob/75492c8b36c9392d94dfce09fc132ce88c94325e/netty/src/main/java/io/grpc/netty/AbstractHttp2Headers.java#L499
There was a problem hiding this comment.
I see there's already a grpc-java issue on this: grpc/grpc-java#10837
There was a problem hiding this comment.
This looks like it was supposed to be fixed in 1.55.0 with grpc/grpc-java#9979. The report I got was using 1.51.1, and grpc/grpc-java#10837 reports using 1.30.2, so this is probably not an issue for those who are on newer versions!
There was a problem hiding this comment.
Oh that's great to hear. I saw the issue this morning as felt, "oh no." Glad it is already added. (Although obviously, better than recently being added would have been "always had been implemented"... We should re-run the benchmarks to see how much of a performance difference it makes to use our own impl, although benchmarking garbage creation is terribly difficult to get meaningful results.)
Motivation:
According to the RFC for HTTP2 on Section 8.1.2.1, 'Pseudo-header fields MUST NOT appear in trailers. Endpoints MUST treat a request or response that contains undefined or invalid pseudo-header fields as malformed (Section 8.1.2.6).'
Modifications:
Updated Http2Decoder to check trailers for Pseudo-Headers and treat them as invalid requests according to RFC 7540 Section 8.1.2.6
Result:
After this change, requests with Pseudo-Headers sent inside trailers will be treated as malformed and a stream error is thrown.
Fixes: #13602