Bug 2536962 (CVE-2026-93569)

Summary: CVE-2026-93569 io.netty/netty-codec-http2: HTTP/1 absolute-form Host mismatch is translated to HTTP/2 :authority, overriding the request-target authority
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: ant, anujha, aschwart, asoldano, aszczucz, ataylor, bbaranow, bmaxwell, boliveir, bstansbe, ccranfor, cescoffi, csuconic, dbruscin, dlofthou, drichtar, ehugonne, ewittman, fmariani, fmongiar, gmalinko, gsmet, gtully, istudens, ivassile, iweiss, janstey, jmartisk, jnethert, jpechane, jsherman, jwon, kvanderr, manderse, mcarlett, mosmerov, mposolda, msvehla, nipatil, nwallace, olubyans, ozzy, pantinor, pberan, pdelbell, pesilva, pjindal, pmackay, rgemmell, rgodfrey, rguimara, rkubis, rmartinc, rstancel, rstepani, sbiarozk, ssilvert, sthorger, tbish, tcunning, thjenkin, tlavocat, varjain, vdosoudi, vmuzikar, yfang
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in Netty. A remote unauthenticated attacker can exploit a vulnerability in Netty's HTTP/1 to HTTP/2 conversion process. When an HTTP/1 request includes both an absolute-form request-target and a conflicting Host header, Netty incorrectly prioritizes the Host header for the HTTP/2 :authority field, discarding the original request-target authority. This inconsistency can allow an attacker to bypass security controls in Netty-based proxies or gateways, potentially leading to unauthorized access, cache poisoning, or misrouting of requests.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-09-18 10:27:49 UTC
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