Bug 2536961 (CVE-2026-93568)

Summary: CVE-2026-93568 io.netty/netty-codec-http2: io.netty/netty-codec-http3: Netty: HTTP/2 and HTTP/3 Extended CONNECT requests are downgraded as regular CONNECT requests
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 attacker could exploit this vulnerability by sending specially crafted HTTP/2 or HTTP/3 Extended CONNECT requests. Netty's HTTP-object conversion path incorrectly processes these requests as regular HTTP/1.1 CONNECT requests, leading to a loss of critical protocol and path information. This misinterpretation can allow attackers to bypass security policies, such as routing or authorization logic, in applications that rely on Netty for HTTP/2 or HTTP/3 communication, resulting in integrity loss.
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:25:32 UTC
HTTP/2 and HTTP/3 Extended CONNECT requests are downgraded as regular CONNECT requests

A public GitHub Security Advisory (GHSA-w6j8-x45j-w75f) describes the following issue:

## Summary

Netty's HTTP/2 and HTTP/3 HTTP-object conversion paths collapse Extended CONNECT requests into ordinary HTTP/1.1 `CONNECT` requests.

An Extended CONNECT request such as:

```text
:method: CONNECT
:protocol: websocket
:scheme: https
:path: /admin/ws
:authority: ws.example:443
```

is converted to an HTTP/1.1 object shaped like:

```text
CONNECT ws.example:443 HTTP/1.1
host: ws.example:443
x-http2-scheme: https
```

or, for HTTP/3:

```text
CONNECT ws.example:443 HTTP/1.1
host: ws.example:443
x-http3-scheme: https
```

The converted request no longer carries the `:protocol` value or the Extended-CONNECT `:path`. A downstream handler using Netty's HTTP-object API therefore cannot distinguish this request from a regular CONNECT tunnel to `ws.example:443`.

That is a semantic security boundary. RFC 8441 defines Extended CONNECT as a different CONNECT mode: the `:protocol` pseudo-header selects the protocol for the stream, `:path` remains part of the target URI, and the server must not treat `:authority` as the host to tunnel to in the same way it would for a regular CONNECT request. RFC 9220 applies the same pseudo-header and setting semantics to HTTP/3.

## Technical Details

HTTP/2:

- `codec-http2/.../HttpConversionUtil.java:272-280` uses `:authority` as the HTTP/1 request URI for every `CONNECT` request.
- `codec-http2/.../HttpConversionUtil.java:328-337` creates a `DefaultHttpRequest` with that URI, then translates headers.
- `codec-http2/.../HttpConversionUtil.java:806-813` maps `:authority` to Host and `:scheme` to `x-http2-scheme`, but does not preserve request `:path`; unrecognized pseudo-headers such as `:protocol` are dropped.

HTTP/3:

- `codec-http3/.../Http3HeadersSink.java:79-94` recognizes Extended CONNECT and requires `:method`, `:scheme`, `:authority`, `:path`, and `:protocol`.
- `codec-http3/.../HttpConversionUtil.java:201-209` uses `:authority` as the HTTP/1 request URI for every `CONNECT` request.
- `codec-http3/.../HttpConversionUtil.java:259-268` creates a `DefaultHttpRequest` with that URI, then translates headers.
- `codec-http3/.../HttpConversionUtil.java:578-585` maps `:authority` to Host and `:scheme` to `x-http3-scheme`, but does not preserve request `:path`; `:protocol` is dropped as a pseudo-header.

The resulting object-level shape is security-relevant because applications and gateway integrations commonly authorize CONNECT differently from WebSocket, WebTransport, MASQUE, or other Extended CONNECT protocols. With Netty's conversion path, a policy that permits regular CONNECT to an allowlisted authority can be applied to an Extended CONNECT request whose actual protocol and path were erased before application code sees it.

## Impact

A remote HTTP/2 or HTTP/3 client can send an Extended CONNECT request that Netty presents to downstream HTTP-object handlers as a regular CONNECT tunnel.

In gateway, proxy, application-server, or protocol-bridging deployments that use Netty's HTTP-object conversion path, this can bypass routing or authorization logic that is meant to distinguish:

- regular CONNECT tunnels from WebSocket/WebTransport/MASQUE-style Extended CONNECT streams;
- allowed CONNECT authorities from protected Extended-CONNECT paths;
- enabled/registered Extended CONNECT protocols from ordinary CONNECT traffic.

This report does not claim memory corruption, code execution, confidentiality impact, or impact on applications that never route HTTP/2 or HTTP/3 requests through Netty's HTTP-object adapters. The demonstrated impact is integrity loss through protocol-state confusion before application policy runs.

## Suggested Fix

Recommended fix direction:

- do not convert Extended CONNECT into an ordinary HTTP/1 `CONNECT` object without preserving the Extended-CONNECT state;
- either reject Extended CONNECT in `HttpConversionUtil.toHttpRequest(...)` unless Netty can expose the state safely, or preserve it with explicit extension headers such as `x-http2-protocol` / `x-http3-protocol` and `x-http2-path` / `x-http3-path` for request conversion;
- keep regular CONNECT behavior unchanged;
- add regression tests covering direct conversion and the frame-to-object adapters for both HTTP/2 and HTTP/3;
- add controls proving regular CONNECT and Extended CONNECT no longer produce the same HTTP-object shape.

If maintainers prefer not to support Extended CONNECT through the HTTP-object API, the safest fix is to fail closed and require users to handle it at the native HTTP/2 or HTTP/3 frame/header layer.

## References

- Netty security policy: https://github.com/netty/netty/security/policy
- RFC 8441, Extended CONNECT: https://datatracker.ietf.org/doc/html/rfc8441#section-4
- RFC 9220, WebSockets over HTTP/3: https://datatracker.ietf.org/doc/html/rfc9220#section-3
- RFC 9113, HTTP/2 request pseudo-header fields: https://datatracker.ietf.org/doc/html/rfc9113#section-8.3.1
- RFC 9114, HTTP/3 request pseudo-header fields and CONNECT: https://datatracker.ietf.org/doc/html/rfc9114#section-4.3.1
- Go HTTP/2 Extended CONNECT implementation note requiring negotiation before use: https://go.dev/src/net/http/h2_bundle.go
- Go issue discussing Extended CONNECT API concerns: https://github.com/golang/go/issues/27244

## Affected Products

- `io.netty:netty-codec-http2`
- `io.netty:netty-codec-http3`

Confirmed affected:

- current `4.2` branch at `7bae566a93e69409697fe57fa807910ba5c9720e`
- `netty-4.2.15.Final` at `a41f7b289ce1d697c50846f3ade3983e22b2ed40`
- `netty-4.2.2.Final` at `660edeaefa` for HTTP/2
- `netty-4.2.0.Final` at `09e64d259c99` for HTTP/2
- `netty-4.1.135.Final` at `f05f765d81460799c53123a207f665bf3b465171` for HTTP/2

Suggested affected ranges:

- `io.netty:netty-codec-http2 >= 4.1.64.Final, <= 4.1.135.Final`
- `io.netty:netty-codec-http2 >= 4.2.0.Final, <= 4.2.15.Final`
- `io.netty:netty-codec-http3 >= 4.2.8.Final, <= 4.2.15.Final`

The HTTP/2 lower 

[truncated]

Affected:
- maven:io.netty:netty-codec-http2 affected >= 4.1.64.Final, <= 4.1.137.Final; fixed unknown
- maven:io.netty:netty-codec-http2 affected >= 4.2.0.Final, <= 4.2.17.Final; fixed unknown
- maven:io.netty:netty-codec-http3 affected >= 4.2.8.Final, <= 4.2.15.Final; fixed unknown

Fixed versions: see advisory

Advisory: https://github.com/netty/netty/security/advisories/GHSA-w6j8-x45j-w75f