Skip to content

NMS-20088: Fixed CVE-2026-6790 - #3

Open
christianpape wants to merge 1 commit into
jetty-9.4.xfrom
jira/NMS-20088
Open

NMS-20088: Fixed CVE-2026-6790#3
christianpape wants to merge 1 commit into
jetty-9.4.xfrom
jira/NMS-20088

Conversation

@christianpape

@christianpape christianpape commented Jul 28, 2026

Copy link
Copy Markdown

Jetty 9.4 accepted requests where the request-target authority and the Host header disagree, so one request carried two host identities:
request.getServerName()/getServerURL() resolved from the authority, while request.getHeader("Host") returned something else. It applies to two paths here:

  • HTTP/2 — :authority vs. host (the advisory's case; MetaDataBuilder folds Host into the authority only when :authority is absent, and
    never compares the two).
  • HTTP/1.1 — absolute request URI vs. Host (HttpChannelOverHttp ignores Host when the URI is absolute). Upstream fixed this in 10.0.14 via
    URI Host Mismatch with optional Compliance modes jetty/jetty.project#9343; that fix was never backported to 9.4, so this fork was vulnerable there too.

There is no HTTP/3 in 9.4, so that part of the advisory doesn't apply.

The fix

Rather than duplicating a check per protocol, it goes at the one choke point both paths pass through, Request.setMetaData() (jetty-server/src/main/java/org/eclipse/jetty/server/Request.java:1837) — the same place upstream chose for 10.x. Mismatches throw BadMessageException(400), which HttpChannelOverHTTP2.onRequest and the HTTP/1.1 channel both turn into a 400 response.

Matching normalizes the way upstream's 12.1 ComplianceUtils.authorityMatches does: case-insensitive, default port for the scheme treated as equivalent to an absent port, and an unparseable Host counted as a mismatch. Every Host field is checked, not just the first, so a second smuggled Host behind a matching one is also rejected.

Two supporting changes:

  • HttpComplianceSection.MISMATCHED_AUTHORITY added, enforced by RFC7230* (the defaults) and excluded from RFC2616 — mirroring upstream, since RFC 2616 §5.2 deliberately gives the absolute URI precedence. Deployments that need the old behavior select RFC2616 (or add an HttpCompliance bean to the connector, for HTTP/2).
  • PushBuilderImpl now sets the pushed request's Host from its own URI authority. Without this, a pushed request would inherit the original Host while deriving its authority from a customizer-rewritten name (e.g. behind ForwardedRequestCustomizer), and the new check would 400 it.

Tests

Two new classes, MismatchedAuthorityTest in jetty-server (14 tests, HTTP/1.1) and in jetty-http2/http2-client (8 tests, HTTP/2 end-to-end): rejection of mismatched host, mismatched port, garbage Host, and smuggled second Host; acceptance of matching authority, case differences, implied vs. explicit default port, IPv6, and no-Host; plus the RFC2616 opt-out. I verified they fail on the unpatched tree — 5 of 14 and 4 of 8 respectively — and pass with the fix.

Four existing suites asserted the old permissive behavior and were updated the way upstream did: RequestTest.testHostPort now expects 400 plus a matching-host case, NcsaRequestLogTest.testAbsolute uses a matching Host, and PartialRFC2616Test, ForwardedRequestCustomizerTest and the NIOHttp(s).xml integration configs select RFC2616.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants