Skip to content

Make Content-Length handling strict - #324

Merged
kou merged 1 commit into
ruby:masterfrom
kou:strict-response-content-length
Aug 26, 2026
Merged

Make Content-Length handling strict#324
kou merged 1 commit into
ruby:masterfrom
kou:strict-response-content-length

Conversation

@kou

@kou kou commented Aug 25, 2026

Copy link
Copy Markdown
Member

Content-Length value must have only digits.

See also RFC 9110 Section 8.6:
https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6

Content-Length = 1*DIGIT

The current implementation accepts garbage before/after digits such as abc5 and 5abc.

This rejects these invalid values.

But this accepts same values in one Content-Length

Content-Length: 5, 5

and in multiple Content-Lengthes:

Content-Length: 5
Content-Length: 5

This is for the following part in the RFC:

https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-13

Likewise, a sender MUST NOT forward a message with a Content-Length
header field value that does not match the ABNF above, with one
exception: a recipient of a Content-Length header field value
consisting of the same decimal value repeated as a comma-separated
list (e.g, "Content-Length: 42, 42") MAY either reject the message
as invalid or replace that invalid field value with a single
instance of the decimal value, since this likely indicates that a
duplicate was generated or combined by an upstream message
processor.

@kou
kou force-pushed the strict-response-content-length branch 2 times, most recently from 7b0e9b6 to 22238b9 Compare August 25, 2026 03:04
Comment thread test/net/http/utils.rb
Comment on lines -212 to +214
@headers['Transfer-Encoding'] = 'chunked'
self['Transfer-Encoding'] = 'chunked'
else
@headers['Content-Length'] = @body.bytesize.to_s
self['Content-Length'] ||= @body.bytesize.to_s

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must use self[]= not @headers[]= here because self[]= uses downcase.

@hsbt

hsbt commented Aug 25, 2026

Copy link
Copy Markdown
Member

An empty Content-Length field is silently dropped when another field carries a value, so the response is accepted instead of rejected.

Content-Length: 5
Content-Length:
# => content_length returns 5

Content-Length:
# => Net::HTTPHeaderSyntaxError: Content-Length has multiple different values:

"".split(/\s*,\s*/, -1) returns [], not [""], so an empty field contributes no element to lengths. In the first case it vanishes and validation passes. In the second case lengths is empty, lengths.uniq.size != 1 is true for zero elements, and the message reports a duplicate that does not exist. The old code raised wrong Content-Length format there.

`Content-Length` value must have only digits.

See also RFC 9110 Section 8.6:
https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6

    Content-Length = 1*DIGIT

The current implementation accepts garbage before/after digits such as
`abc5` and `5abc`.

This rejects these invalid values.

But this accepts same values in one `Content-Length`

    Content-Length: 5, 5

and in multiple `Content-Length`es:

    Content-Length: 5
    Content-Length: 5

This is for the following part in the RFC:

https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-13

> Likewise, a sender MUST NOT forward a message with a Content-Length
> header field value that does not match the ABNF above, with one
> exception: a recipient of a Content-Length header field value
> consisting of the same decimal value repeated as a comma-separated
> list (e.g, "Content-Length: 42, 42") MAY either reject the message
> as invalid or replace that invalid field value with a single
> instance of the decimal value, since this likely indicates that a
> duplicate was generated or combined by an upstream message
> processor.
@kou
kou force-pushed the strict-response-content-length branch from 22238b9 to 2635a7e Compare August 25, 2026 07:51

@hsbt hsbt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@kou
kou merged commit 23e859e into ruby:master Aug 26, 2026
26 checks passed
matzbot pushed a commit to ruby/ruby that referenced this pull request Aug 26, 2026
(ruby/net-http#324)

`Content-Length` value must have only digits.

See also RFC 9110 Section 8.6:
https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6

    Content-Length = 1*DIGIT

The current implementation accepts garbage before/after digits such as
`abc5` and `5abc`.

This rejects these invalid values.

But this accepts same values in one `Content-Length`

    Content-Length: 5, 5

and in multiple `Content-Length`es:

    Content-Length: 5
    Content-Length: 5

This is for the following part in the RFC:

https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-13

> Likewise, a sender MUST NOT forward a message with a Content-Length
> header field value that does not match the ABNF above, with one
> exception: a recipient of a Content-Length header field value
> consisting of the same decimal value repeated as a comma-separated
> list (e.g, "Content-Length: 42, 42") MAY either reject the message
> as invalid or replace that invalid field value with a single
> instance of the decimal value, since this likely indicates that a
> duplicate was generated or combined by an upstream message
> processor.

ruby/net-http@23e859e92e
@kou
kou deleted the strict-response-content-length branch August 26, 2026 00:48
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