Make HTTP 1 the only HTTP version we support

Hi all,

Currently, https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/ServletContainerSupportStrategy/ says nothing about which HTTP version we support.

Consequently, we receive and handle HTTP/2 issues:

Based on my current understanding, we don’t have much to gain from supporting other versions of HTTP:

  • XWiki is often server through a reverse proxy, that support and benefit from HTTP/2
  • Between the reverse proxy and the servlet container, HTTP/1.1 remains the default and what our nginx documentation configures.
  • Jetty standalone don’t serve HTTP/2: we strip the http2 and http3 modules as supporting TLS would add complexity for not much gain
  • Enabling HTTP/2 on the servlet container increases the attack surface: the cleartext upgrade (h2c) behind a proxy allows bypassing the proxy’s access controls, and HTTP/2 implementations have a history of denial of service vulnerabilities (Rapid Reset, CONTINUATION flood, which included a Tomcat CVE).
  • I believe the same arguments apply for HTTP/3

By stating explicitly that we only support HTTP/1, I think that we would benefit from:

  1. Being able to reject/prioritize related issues easily
  2. Avoid having to extend our functional tests to cover more HTTP versions.

Proposal:
XWiki only support HTTP/1 at servlet container level. Maintainers can fix issues related to other HTTP versions (e.g., Loading...) on the best effort basis.
This includes only providing pre-packaged versions of XWiki with an HTTP/1 support (e.g., Jetty standalone, docker images).
XWiki keeps documenting reverse proxy configurations allowing to access XWiki using other HTTP versions.

I’ll update https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/ServletContainerSupportStrategy/ accordingly once we reach an agreement.

Here is my +1, thanks

Hi Manuel,

I agree with the general idea, but I’d tweak the wording a bit.

I agree that for the common setup (reverse proxy + servlet container), HTTP/2 between the proxy and the container doesn’t bring much. Its main benefit is multiplexing lots of small requests over a high-latency link, and that’s the browser ↔ proxy link, which already works. nginx doesn’t even speak HTTP/2 to backends. On xwiki.org a doc page makes ~155 requests, 139 of them under 10 KB, so HTTP/2 does matter for XWiki, but at the proxy level.

However:

  1. The bugs are in our code, not in HTTP/2. I did some archeology. XWIKI-15768 (2018) looked up a component using the protocol string. XWIKI-18513 relies on statusText. XWIKI-25202 (the cause of the 3 forum threads) is us putting newlines in a header, which the HTTP/2 spec forbids and which Tomcat silently cleans up for us over HTTP/1.1. These are spec-compliance bugs and cheap to fix, so I think we should keep handling them as normal bugs, not best effort.
  2. The security argument cuts both ways. h2c is a real risk, and I agree we should explicitly discourage it. But James Kettle’s 2025 research (“HTTP/1.1 Must Die”, HTTP/1.1 must die: the desync endgame | PortSwigger Research) argues that HTTP/1.1 between the proxy and the backend is the inherently smuggling-prone part, and that upstream HTTP/2 is the fix. So I wouldn’t present “HTTP/1.1 only” as a security measure.
  3. Some users run Tomcat with TLS directly, without a proxy. For them HTTP/2 is a real performance gain.

So my proposal: state that HTTP/1.1 is the tested and recommended protocol at the servlet container level, that the recommended way to get HTTP/2 or HTTP/3 is a reverse proxy, and that h2c is discouraged. Keep the packaged distributions on HTTP/1.1 and don’t extend our functional tests, but keep fixing HTTP/2 incompatibilities in our code as regular bugs.

With that, +1.

Thanks

Thanks for rephrasing. I think it captures better what I had in mind.

So moving my +1 to this proposal.

+1