Jetty currently accepts HTTP/2 and HTTP/3 requests where the regular Host header and the pseudo-header :authority do not match. As a result, the same request can carry two different host identities through Jetty:
HttpURI / Request.getServerName(request) uses :authorityHostThis creates a host/authority confusion condition that can break security assumptions in higher layers.
Jetty already performs an explicit authority/Host consistency check on the HTTP/1.1 path, but equivalent validation is missing on the HTTP/2 and HTTP/3 paths.
This issue is not inherently remote code execution, but it can become security-relevant in deployments that rely on the request host for security-sensitive decisions, including:
Potential consequences include:
:authority is parsed separately into authority/URI stateHost is preserved as a normal request headerComplianceUtils.verify(httpCompliance, requestMetaData, listener)MISMATCHED_AUTHORITYHost matchHTTP/2 metadata builder:
jetty-core/jetty-http2/jetty-http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/internal/MetaDataBuilder.javaHTTP/3 metadata builder:
jetty-core/jetty-http3/jetty-http3-qpack/src/main/java/org/eclipse/jetty/http3/qpack/internal/metadata/MetaDataBuilder.javaHTTP/2 server entry:
jetty-core/jetty-http2/jetty-http2-server/src/main/java/org/eclipse/jetty/http2/server/internal/HttpStreamOverHTTP2.javaHTTP/3 server entry:
jetty-core/jetty-http3/jetty-http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/HttpStreamOverHTTP3.javaShared HTTP compliance verification:
jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/ComplianceUtils.javaHTTP/1.1 authority/Host consistency check:
jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.javaDefined but not enforced on H2/H3:
jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.javaI reproduced this on local Jetty 12.1.9-SNAPSHOT source.
Minimal reproduction steps:
This shows that a single attacker-controlled request can preserve two conflicting host interpretations inside Jetty.
HTTP/2 rejection test:
org.eclipse.jetty.http2.tests.HTTP2Test#testRejectMismatchedHostHeaderAndAuthorityHTTP/2 exploitability test:
org.eclipse.jetty.http2.tests.HTTP2Test#testMismatchedHostHeaderAndAuthoritySplitsAuthorityFromHostHeaderHTTP/3 rejection test:
org.eclipse.jetty.http3.tests.HandlerClientServerTest#testRejectMismatchedHostHeaderAndAuthorityHTTP/3 exploitability test:
org.eclipse.jetty.http3.tests.HandlerClientServerTest#testMismatchedHostHeaderAndAuthoritySplitsAuthorityFromHostHeaderObserved behavior:
Examples:
jetty-openid uses Request.getServerName(request) to construct redirect URLsjetty-ee11-proxy uses the raw Host header when building ForwardedThis indicates that the issue is not merely theoretical: Jetty’s own ecosystem already contains code paths where different host sources are used for different purposes.
Confirmed affected version:
Other versions may also be affected if they share the same HTTP/2 / HTTP/3 request construction and compliance-validation logic. I have not yet completed a historical version matrix and would recommend confirming exact affected ranges from Jetty’s branch history.
Recommend adding HTTP/2 and HTTP/3 validation equivalent to the existing HTTP/1.1 authority/Host consistency check:
Also adding explicit HTTP/2 and HTTP/3 regression coverage for this case.
{
"cwe_ids": [
"CWE-20"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-22T22:56:43Z",
"nvd_published_at": "2026-07-14T09:16:41Z",
"severity": "MODERATE"
}