Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for deprecated obs-fold in header values #53505

Merged
merged 2 commits into from
Jul 15, 2021

Conversation

MihaZupan
Copy link
Member

@MihaZupan MihaZupan commented May 31, 2021

RFC7230 deprecated support for line-folding in header values (emphasis mine):

Historically, HTTP header field values could be extended over
multiple lines by preceding each extra line with at least one space
or horizontal tab (obs-fold). This specification deprecates such
line folding except within the message/http media type
(Section 8.3.1). A sender MUST NOT generate a message that includes
line folding
(i.e., that has any field-value that contains a match to
the obs-fold rule) unless the message is intended for packaging
within the message/http media type.

Previously headers like foo: a\r\n b were considered valid (space following new line).

This PR removes obs-fold support from header validation, instead treating all new line characters as invalid.

On the receiving side, servers MAY accept obs-fold as long as they replace new lines with spaces.

A server that receives an obs-fold in a request message that is not
within a message/http container MUST either reject the message by
sending a 400 (Bad Request), preferably with a representation
explaining that obsolete line folding is unacceptable, or replace
each received obs-fold with one or more SP octets prior to
interpreting the field value
or forwarding the message downstream.

Kestrel will treat the whole request as invalid and close the connection when receiving such a header.
HttpClient today does accept them in responses - this PR does not change that.

Fixes #50597

@MihaZupan MihaZupan added this to the 6.0.0 milestone May 31, 2021
@MihaZupan MihaZupan requested a review from a team May 31, 2021 17:24
@MihaZupan MihaZupan self-assigned this May 31, 2021
@ghost
Copy link

ghost commented May 31, 2021

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

RFC7230 deprecated support for line-folding in header values (emphasis mine):

Historically, HTTP header field values could be extended over
multiple lines by preceding each extra line with at least one space
or horizontal tab (obs-fold). This specification deprecates such
line folding except within the message/http media type
(Section 8.3.1). A sender MUST NOT generate a message that includes
line folding
(i.e., that has any field-value that contains a match to
the obs-fold rule) unless the message is intended for packaging
within the message/http media type.

Previously headers like foo: a\r\n b were considered valid (space following new line).

This PR removes obs-fold support from header validation, instead treating all new line characters as invalid.

On the receiving side, servers MAY accept obs-fold as long as they replace new lines with spaces.

A server that receives an obs-fold in a request message that is not
within a message/http container MUST either reject the message by
sending a 400 (Bad Request), preferably with a representation
explaining that obsolete line folding is unacceptable, or replace
each received obs-fold with one or more SP octets prior to
interpreting the field value
or forwarding the message downstream.

Kestrel will treat the whole request as invalid and close the connection when receiving such a header.
HttpClient today does accept it - this PR does not change that.

Fixes #50597

Author: MihaZupan
Assignees: MihaZupan
Labels:

area-System.Net.Http

Milestone: 6.0.0

@geoffkizer
Copy link
Contributor

What's the motivation for doing this?

I'm concerned that we will break some customer that is relying on this.

@MihaZupan MihaZupan force-pushed the header-valid branch 2 times, most recently from e35f6ec to 24349a5 Compare June 15, 2021 18:17
Copy link
Contributor

@geoffkizer geoffkizer left a comment

Choose a reason for hiding this comment

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

Actually, I think this is missing some relevant changes.

HttpRuleParser.GetWhitespaceLength should be updated.

@MihaZupan
Copy link
Member Author

MihaZupan commented Jul 15, 2021

Note: the change may seem huge, but it's 95% test changes

Product changes:

  • Changed ContainsInvalidNewLine to ContainsNewLine
  • Removed CRLF support from HttpRuleParser.GetWhitespaceLength
  • Added CRLF check to HttpRuleParser.GetExpressionLength, NameValueHeaderValue's CheckValueFormat, HttpRequestHeaders.From* and AuthenticationHeaderValue's parameter

*after #52794, setting the From property would bypass new line checks (Add("From", "Foo") would still do the check).

@MihaZupan
Copy link
Member Author

/azp run runtime

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

Product changes LGTM, and I skimmed the tests. Do we have tests that validate all forms of newline are still allowed with TryAddWithoutValidation and NonValidated headers?

@MihaZupan
Copy link
Member Author

Yes, I added a bunch of new-line combinations to this TryAddWithoutValidation/NonValidated test

[Theory]
[MemberData(nameof(HeaderValuesWithNewLines))]
public void TryAddWithoutValidation_AddValueContainingNewLine_Rejected(string headerValue)

@MihaZupan MihaZupan dismissed geoffkizer’s stale review July 15, 2021 16:37

Comment has been addressed

@MihaZupan MihaZupan merged commit 0733681 into dotnet:main Jul 15, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Aug 14, 2021
@geoffkizer
Copy link
Contributor

Do we have tests that validate all forms of newline are still allowed with TryAddWithoutValidation and NonValidated headers?

I'm looking at the tests you referenced @MihaZupan and it looks like all forms of newline are NOT allowed with TryAddWithoutValidation.

In particular it looks like the HeaderValuesWithNewLines enumerable is explicitly testing that we disallow these.

Am I missing something here? I thought the idea was to continue to allow obs-fold when using TryAddWithoutValidation but to restrict it elsewhere. Is this broken now?

@MihaZupan
Copy link
Member Author

MihaZupan commented Sep 2, 2021

@geoffkizer We continue to do no validation with TryAddWithoutValidation. The test name is bad, but we are testing that new lines added without validation will be present when we enumerate without validation.

Assert.Equal(headerValue, headers.NonValidated["foo"].ToString());

It is also testing that accessing the header with validation will result in its removal.

@geoffkizer
Copy link
Contributor

It is also testing that accessing the header with validation will result in its removal.

Why is it removed if it is a valid header with embedded obs-fold?

@MihaZupan
Copy link
Member Author

If you access a header with validation and we consider it as invalid, it will be removed from the collection. This has been the existing behavior.

The change is that now we treat any new lines as invalid - even if it would have been a valid obs fold.

In other words, you can only work with obs-folds if you add them without validation and read them without validation.

What behavior did you have in mind as desired here?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HttpRequestMessage.Headers.Add should validate the header value
3 participants