[PATCH 2 of 2] HTTP/2: finalize request as bad if header validation fails

Maxim Dounin mdounin at mdounin.ru
Thu Mar 9 00:40:26 UTC 2023


On Wed, Mar 08, 2023 at 06:15:18PM +0400, Roman Arutyunyan wrote:

> Hi,
> On Wed, Feb 22, 2023 at 03:55:28PM +0300, Maxim Dounin wrote:
> > # HG changeset patch
> > # User Maxim Dounin <mdounin at mdounin.ru>
> > # Date 1677070454 -10800
> > #      Wed Feb 22 15:54:14 2023 +0300
> > # Node ID ec3819e66f40924efad183c291c850d9ccef16e7
> > # Parent  61bd779a868c4021c232dddfe7abda7e8ad32575
> > HTTP/2: finalize request as bad if header validation fails.
> > 
> > Similarly to 7192:d5a535774861, this avoids spurious zero statuses
> > in access.log, and in line with other header-related errors.
> This is what RFC 9113, 8.2.1. Field Validity, says about header field
> validation:
>   A request or response that contains a field that violates
>   any of these conditions MUST be treated as malformed (Section 8.1.1).
> Also (the previous RFC 7540 did not have this statement):
>   When a request message violates one of these requirements, an implementation
>   SHOULD generate a 400 (Bad Request) status code (see Section 15.5.1 of [HTTP])
> Considering this, responding with HTTP 400 is certainly an improvement compared
> to the current code.  Also, it allows to set a custom error page handler.
> However, not resetting the stream as before is a less obvious change.  If we
> consider nginx an intermediary, the RFC 9113 prescribes us to send stream reset:
>   Intermediaries that process HTTP requests or responses (i.e., any
>   intermediary not acting as a tunnel) MUST NOT forward a malformed
>   request or response. Malformed requests or responses that are detected
>   MUST be treated as a stream error (Section 5.4.2) of type PROTOCOL_ERROR.
> This restriction probably makes sense for the intermediaries unable to handle
> the error in a more flexible way.
> I like the change, but I'd like to hear what you think about the reset issue.

We already do exactly the same for quite similar cases, as 
introduced in 7192:d5a535774861, for unknown and invalid 
pseudo-headers.  This patch simply makes handling of 
errors detected by ngx_http_v2_validate_header() equivalent.

I does not look like returning 400 instead of sending RST_STREAM 
causes any issues.  Further, given that HTTP/2 error handling is 
mostly unimplemented by clients, I tend to think that returning 
400 instead of RST_STREAM is a better option.

Note well that nothing in RFC 7540 actually requires to send 
RST_STREAM: while it says that (detected) malformed requests "MUST 
be treated as a stream error", handling of stream errors does not 
require to actually send RST_STREAM, as there is no such normative 
requirement in section 5.4.2.  Further, RFC 9113 explicitly states 
that (https://www.rfc-editor.org/rfc/rfc9113#section-8.1.1):

  For malformed requests, a server MAY send an HTTP response prior 
  to closing or resetting the stream. 

Note "closing or resetting", which implies that RST_STREAM is not 

While we might consider changing the code to generate RST_STREAM 
after sending the response in such cases, this does not seem to be 
needed (and might actually make things worse).  In either case 
this doesn't look like something to be addressed in this patch 

Maxim Dounin

More information about the nginx-devel mailing list