Fedora Account System
Red Hat Associate
Red Hat Customer
HTTP/1 authority-form CONNECT is translated to malformed HTTP/2 CONNECT with Host-controlled :authority A public GitHub Security Advisory (GHSA-45h4-vhwh-fmhg) describes the following issue: ## Summary Netty's HTTP/1-to-HTTP/2 conversion does not special-case true HTTP/1 CONNECT authority-form request-targets. Instead, `HttpConversionUtil.toHttp2Headers()` applies the generic request conversion path to a request-target like `trusted.example:443`. For example: ```text CONNECT trusted.example:443 HTTP/1.1 Host: attacker.example:443 ``` is converted to HTTP/2 headers with these security-relevant properties: ```text :method: CONNECT :authority: attacker.example:443 :scheme: trusted.example :path: <present> ``` The exact `:path` value has varied across releases (`/` in checked older 4.2.x releases and `trusted.example:443` in current/4.2.15), but the invariant bug is stable: the CONNECT tunnel authority is taken from the HTTP/1 `Host` header instead of the CONNECT authority-form request-target, and Netty emits HTTP/2 CONNECT-forbidden `:scheme` and `:path` pseudo-headers. HTTP/2 CONNECT must omit `:scheme` and `:path`, and `:authority` must contain the host and port from the CONNECT authority-form request-target. In a Netty-based HTTP/1-to-HTTP/2 proxy or gateway, policy that authorizes the HTTP/1 CONNECT request-target can disagree with the upstream HTTP/2 proxy, which receives the Host-controlled `:authority`. ## Technical Details The relevant code is `codec-http2/src/main/java/io/netty/handler/codec/http2/HttpConversionUtil.java`. `toHttp2Headers(HttpMessage, boolean)` handles `HttpRequest` conversion with a generic URI/request-target parser: ```text String host = inHeaders.getAsString(HttpHeaderNames.HOST); ... String requestTarget = request.uri(); out.path(toHttp2Path(requestTarget)); ... setHttp2Scheme(...); setHttp2Authority(host, out); out.method(request.method().asciiName()); ``` For CONNECT, the HTTP/1 request-target is authority-form (`host:port`), not an origin-form path and not an absolute URI. On the current branch, `trusted.example:443` is treated as a scheme-like string for `:scheme`, the request-target is emitted as `:path`, and the HTTP/1 `Host` header is used for `:authority`. On checked older 4.2.x releases, the `:path` value is `/`, but the authority confusion and forbidden pseudo-header emission still reproduce. ## Impact In a Netty HTTP/1-to-HTTP/2 proxy/gateway path, a remote HTTP/1 client can ask to CONNECT to one authority while supplying a different Host header. Netty then builds an HTTP/2 CONNECT request whose tunnel `:authority` is Host-controlled and whose pseudo-header set is malformed. This can bypass tunnel allow-lists, egress policy, backend selection, audit logic, or other security controls that validate the HTTP/1 CONNECT request-target before forwarding over HTTP/2. This report does not claim code execution or memory corruption. The impact is integrity loss through CONNECT tunnel-target confusion at an HTTP/1-to-HTTP/2 conversion boundary. ## Suggested Fix When converting true HTTP/1 authority-form CONNECT to HTTP/2: - set `:method` to `CONNECT`; - set `:authority` from the HTTP/1 CONNECT request-target authority-form; - omit `:scheme` and `:path`; - reject or ignore conflicting Host instead of allowing it to replace the CONNECT target; - add regression tests for direct `toHttp2Headers(...)` and outbound `HttpToHttp2ConnectionHandler` conversion. The attached patched-control diff demonstrates the minimal behavior change: `evidence/minimal-connect-patched-control.diff` The patched-control run passed: ```fish ./mvnw -q -pl codec-http2 \ -Dtest=Http2ConnectAuthorityFormFixedControlTest,HttpToHttp2ConnectionHandlerTest#testAuthorityFormRequestTargetHandled \ -Dsurefire.failIfNoSpecifiedTests=false \ -DskipNativeTests -DskipAutobahnTests -Dmaven.antrun.skip=true test ``` ## Affected Package/Versions `io.netty:netty-codec-http2` Confirmed affected: - current `4.2` branch at `7bae566a93e69409697fe57fa807910ba5c9720e` - `4.2.15.Final` at `a41f7b289ce1d697c50846f3ade3983e22b2ed40` - `4.2.2.Final` at `660edeaefad4a4cedbd61584e8f668ad2d89f0b8` - `4.2.0.Final` at `09e64d259c99be8b5b2a471a78f11e65eb82598a` - `4.1.135.Final` at `f05f765d81460799c53123a207f665bf3b465171` Suggested affected ranges: - `>= 4.1.0.Final, <= 4.1.135.Final` - `>= 4.2.0.Final, <= 4.2.15.Final` ## References - Netty security policy: https://github.com/netty/netty/security/policy - RFC 9113 HTTP/2 CONNECT method: https://datatracker.ietf.org/doc/html/rfc9113#section-8.5 - RFC 9112 authority-form: https://datatracker.ietf.org/doc/html/rfc9112#section-3.2.3 - RFC 9110 CONNECT method: https://datatracker.ietf.org/doc/html/rfc9110#section-9.3.6 ## CWE and CVSS Suggested CWEs: - `CWE-20`: Improper Input Validation - `CWE-436`: Interpretation Conflict - `CWE-444`: Inconsistent Interpretation of HTTP Requests Suggested CVSS v3.1: ```text CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N ``` Suggested severity: High, score 7.5. Rationale: a network peer can trigger this in a proxy/gateway path without authentication. Integrity impact is high because CONNECT can establish a tunnel to an unintended upstream authority when forwarding policy validated a different request-target. ## Duplicate Boundary Nearby reports are distinct: - `GHSA-cg2g-fxr4-mg8m`: HTTP/1 absolute-form Host mismatch to HTTP/2 `:authority`. - `GHSA-jgph-cgq3-c627`: the sibling HTTP/1 CONNECT authority-form conversion bug in `netty-codec-http3`. - `GHSA-w6j8-x45j-w75f`: HTTP/2/HTTP/3 Extended CONNECT inbound downgrade. - `GHSA-gcjj-c5ff-2m72`, `GHSA-xf5f-3m33-p8m3`, and `GHSA-w424-c27v-r9mr`: HTTP/2-to-HTTP/1 inbound downgrade families. This report covers outbound HTTP/1 CONNECT authority-form conversion to HTTP/2. Live duplicate evidence is in `evidence/advisory-duplicate-check.tsv`. ## Local PoV PoV file: `pov/Http2ConnectAuthorityFormHostConfusionPovTest.java` Run from a Netty checkout after copying the PoV file into `codec-http2/src/test/java/io/ [truncated] Affected: - maven:io.netty:netty-codec-http2 affected >= 4.1.0.Final, <= 4.1.137.Final; fixed unknown - maven:io.netty:netty-codec-http2 affected >= 4.2.0.Final, <= 4.2.17.Final; fixed unknown Fixed versions: see advisory Advisory: https://github.com/netty/netty/security/advisories/GHSA-45h4-vhwh-fmhg