Skip to content

Disable tolerantEol by default for HTTP/1.1 header parsing#999

Closed
UserB1ank wants to merge 1 commit into
apache:mainfrom
UserB1ank:fix/disable-tolerant-eol-default
Closed

Disable tolerantEol by default for HTTP/1.1 header parsing#999
UserB1ank wants to merge 1 commit into
apache:mainfrom
UserB1ank:fix/disable-tolerant-eol-default

Conversation

@UserB1ank
Copy link
Copy Markdown

Change Http11InputBuffer to construct HttpHeaderParser with tolerantEol=false instead of true, requiring strict CRLF line endings in HTTP headers per RFC 7230.

While RFC 7230 Section 3.5 permits recipients to accept bare LF as a line terminator, doing so by default creates a security risk when Tomcat is deployed behind a reverse proxy (nginx, AWS ALB, Cloudflare, etc.) that enforces strict CRLF parsing.

In this common deployment topology, the proxy and Tomcat interpret the same raw bytes differently: the proxy sees one header value (containing the bare LF), while Tomcat's tolerantEol=true parses the bare LF as a header separator, splitting it into two headers. This semantic discrepancy enables:

  • HTTP Header Injection via bare LF in header values
  • Trust header forgery (X-Forwarded-For, X-Real-IP, etc.)
  • Potential HTTP Request Smuggling with strict-CRLF proxies

This change only affects header parsing. Request line parsing in Http11InputBuffer.parseRequestLine() accepts bare LF independently (for HTTP/1.0 compatibility) and is not affected.

Trailer headers in ChunkedInputFilter already use
tolerantEol=false and are not affected.

Impact: Non-conforming clients that send bare LF in headers will receive a 400 response. Modern clients and proxies all use CRLF.

Change Http11InputBuffer to construct HttpHeaderParser with
tolerantEol=false instead of true, requiring strict CRLF line
endings in HTTP headers per RFC 7230.

While RFC 7230 Section 3.5 permits recipients to accept bare LF
as a line terminator, doing so by default creates a security risk
when Tomcat is deployed behind a reverse proxy (nginx, AWS ALB,
Cloudflare, etc.) that enforces strict CRLF parsing.

In this common deployment topology, the proxy and Tomcat interpret
the same raw bytes differently: the proxy sees one header value
(containing the bare LF), while Tomcat's tolerantEol=true parses
the bare LF as a header separator, splitting it into two headers.
This semantic discrepancy enables:

- HTTP Header Injection via bare LF in header values
- Trust header forgery (X-Forwarded-For, X-Real-IP, etc.)
- Potential HTTP Request Smuggling with strict-CRLF proxies

This change only affects header parsing. Request line parsing
in Http11InputBuffer.parseRequestLine() accepts bare LF
independently (for HTTP/1.0 compatibility) and is not affected.

Trailer headers in ChunkedInputFilter already use
tolerantEol=false and are not affected.

Impact: Non-conforming clients that send bare LF in headers will
receive a 400 response. Modern clients and proxies all use CRLF.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@markt-asf
Copy link
Copy Markdown
Contributor

This PR and, more specifically, the false claims that there is security risk in accepting a bare LF as a line terminator is hereby rejected.

@markt-asf markt-asf closed this Apr 29, 2026
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.

2 participants