Fedora Account System
Red Hat Associate
Red Hat Customer
HTTP/1 absolute-form Host mismatch is translated to HTTP/2 :authority, overriding the request-target authority A public GitHub Security Advisory (GHSA-cg2g-fxr4-mg8m) describes the following issue: ## Summary `HttpConversionUtil.toHttp2Headers(...)` translates an HTTP/1 request with an absolute-form request-target and a conflicting `Host` header into HTTP/2 using the `Host` header as `:authority`. For example, this raw HTTP/1 request: ```http GET http://request-target.example/admin HTTP/1.1 Host: host-header.example ``` is translated by Netty into HTTP/2 control data with: ```text :scheme = http :path = /admin :authority = host-header.example ``` The request-target authority `request-target.example` is discarded because Netty only takes the absolute-form request-line authority when the `Host` header is empty. This creates a host/authority confusion primitive in Netty-based HTTP/1 to HTTP/2 proxy or gateway pipelines. A security decision made against the absolute-form request-target authority can be bypassed when Netty forwards the request over HTTP/2 using attacker-controlled `Host` as `:authority`. ## Technical Details In `codec-http2/src/main/java/io/netty/handler/codec/http2/HttpConversionUtil.java`, `toHttp2Headers(...)` initializes `host` from the HTTP/1 `Host` header: ```java String host = inHeaders.getAsString(HttpHeaderNames.HOST); ``` For non-origin-form requests, it parses the request target and sets the HTTP/2 path: ```java String requestTarget = request.uri(); out.path(toHttp2Path(requestTarget)); ``` When the request-target has a scheme and authority, Netty parses the scheme/authority portion, but only uses that authority if `Host` was empty: ```java URI requestTargetUri = URI.create(http2PathlessRequestTarget(requestTarget)); // Take from the request-line if HOST header was empty host = isNullOrEmpty(host) ? requestTargetUri.getAuthority() : host; setHttp2Scheme(inHeaders, requestTargetUri, out); ``` Finally, Netty emits `:authority` from `host`: ```java setHttp2Authority(host, out); ``` The result is that a conflicting `Host` header overrides the authoritative absolute-form request-target authority during HTTP/1 to HTTP/2 conversion. ## Impact In a Netty-based proxy or gateway that accepts HTTP/1, performs access control, routing, tenant selection, egress allowlisting, or cache-keying based on the absolute-form request-target, and then forwards the request over HTTP/2 using `HttpConversionUtil.toHttp2Headers(...)`, an attacker can send: ```http GET http://allowed.example/admin HTTP/1.1 Host: blocked-or-attacker.example ``` The gateway can approve the request based on `allowed.example`, while Netty emits an HTTP/2 request with `:authority=blocked-or-attacker.example`. This can bypass host or tenant security boundaries, poison cross-host cache entries, or route requests to an unintended upstream. The primitive is not a generic application Host-header trust issue; it is a protocol-conversion inconsistency inside Netty's HTTP/1 to HTTP/2 translation helper. ## Suggested Fix Recommended fix direction: - If the HTTP/1 request-target is absolute-form and contains an authority component, construct HTTP/2 `:authority` from that request-target authority. - Alternatively, reject conversion when absolute-form request-target authority and `Host` differ after scheme-based normalization. - Preserve current origin-form behavior where `Host` is the authority source. - Add regression tests for mismatched absolute-form authority/Host, matching authority/Host, origin-form Host, userinfo stripping, IPv6 literals, and explicit ports. ## Affected Package/Versions Primary package: `io.netty:netty-codec-http2` Related package: `io.netty:netty-codec-http` Confirmed affected: - current `4.2` branch at `7bae566a93e69409697fe57fa807910ba5c9720e` - `4.2.15.Final` at `a41f7b289ce1d697c50846f3ade3983e22b2ed40` - `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 9112 request-target and absolute-form rules: https://datatracker.ietf.org/doc/html/rfc9112#section-3.2 - RFC 9113 request pseudo-header fields: https://datatracker.ietf.org/doc/html/rfc9113#section-8.3.1 - RFC 9110 `http` URI authority syntax: https://datatracker.ietf.org/doc/html/rfc9110#section-4.2.1 - HTTPWG mismatching absolute URI and Host discussion: https://github.com/httpwg/http-core/issues/191 - HTTPWG absolute-form precedence clarification: https://github.com/httpwg/http-core/issues/1105 - Netty HTTP/2 content-length request smuggling advisory: https://github.com/advisories/GHSA-f256-j965-7f32 - Netty HTTP/2 request-smuggling validation advisory: https://github.com/advisories/GHSA-wm47-8v5p-wjpj ## CWE and CVSS Primary CWE: `CWE-444` (Inconsistent Interpretation of HTTP Requests). Secondary CWE: `CWE-20` (Improper Input Validation / protocol normalization). Suggested CVSS v3.1: ```text CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N ``` Suggested severity: High, score 8.1. Rationale: a remote unauthenticated HTTP/1 client can trigger the conversion differential in a gateway/proxy deployment. The strongest impact is integrity: host, tenant, egress, or route policy can be checked against one authority and forwarded over HTTP/2 to another. Availability impact is not claimed. ## Duplicate Boundary Adjacent public Netty advisories cover different surfaces: - `GHSA-f256-j965-7f32` / `CVE-2021-21409`: HTTP/2 request smuggling due content-length validation. - `GHSA-wm47-8v5p-wjpj` / `CVE-2021-21295`: HTTP/2 request smuggling due missing validation. - `GHSA-c7h2-758g-pf5v`: private triage item for HTTP/2 `:path` HTAB surviving HTTP/1 downgrade. This candidate is HTTP/1 absolute-form to HTTP/2 `:authority` translation. It does not rely on content-length ambiguity, HTTP/2-to-HTTP/1 downgrade, or request-line whitespace. ## Local PoV PoV file in the local bundle: `po [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-cg2g-fxr4-mg8m