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:
logic based on HttpURI / Request.getServerName(request) uses :authority
logic based on raw request headers continues to use Host
This 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.
Security Impact
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:
host-based access control
virtual host isolation
multi-tenant routing by hostname
login/logout/callback URL construction
reverse proxy and forwarded-header trust chains
auditing, cache keys, and absolute URL generation
Potential consequences include:
bypass of host-based ACLs
virtual host or tenant isolation failures
incorrect or attacker-influenced redirect/callback targets
inconsistent proxy/downstream interpretation of the original target host
misleading logs and audit records
Technical Root Cause
On the HTTP/2 and HTTP/3 metadata builder paths:
:authority is parsed separately into authority/URI state
both rejection tests fail because Jetty returns 200 instead of 400
both exploitability tests pass, confirming that Jetty exposes different host values to different layers
Project-Internal Evidence of Real Impact
Examples:
jetty-openid uses Request.getServerName(request) to construct redirect URLs
jetty-ee11-proxy uses the raw Host header when building Forwarded
This 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.
Affected Version
Confirmed affected version:
12.1.9-SNAPSHOT
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.
Suggested Fix
Recommend adding HTTP/2 and HTTP/3 validation equivalent to the
existing HTTP/1.1 authority/Host consistency check:
if both :authority and regular Host are present
normalize and compare them
if they do not match, reject the request with 400 Bad Request
route the failure through the existing MISMATCHED_AUTHORITY compliance mechanism
Also adding explicit HTTP/2 and HTTP/3 regression coverage for this case.
Disclosure Status
not publicly disclosed
no public issue filed
shared only privately with the Jetty security contacts