From c36f72e7d671e07abc4881cedd080d23f5f73d46 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 15:51:19 +0000 Subject: [PATCH 1/4] Initial plan From 36004b8d5af2598fd19e5709f20eaddc4f513044 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:21:39 +0000 Subject: [PATCH 2/4] Change HttpHeaders.Remove and Contains to return false instead of throwing for disallowed/invalid header names Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/d0ce6ca6-9f52-4275-b304-1ea2502913cc Co-authored-by: MihaZupan <25307628+MihaZupan@users.noreply.github.com> --- .../System/Net/Http/Headers/HttpHeaders.cs | 4 +- .../Headers/HttpContentHeadersTest.cs | 20 ++++++++ .../UnitTests/Headers/HttpHeadersTest.cs | 48 +++++++------------ .../Headers/HttpRequestHeadersTest.cs | 20 +++++++- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs index 214fc794da350d..4fc0236161ece5 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs @@ -309,7 +309,7 @@ internal bool TryGetValues(HeaderDescriptor descriptor, [NotNullWhen(true)] out return false; } - public bool Contains(string name) => Contains(GetHeaderDescriptor(name)); + public bool Contains(string name) => TryGetHeaderDescriptor(name, out HeaderDescriptor descriptor) && Contains(descriptor); public override string ToString() { @@ -478,7 +478,7 @@ internal void SetOrRemoveParsedValue(HeaderDescriptor descriptor, object? value) } } - public bool Remove(string name) => Remove(GetHeaderDescriptor(name)); + public bool Remove(string name) => TryGetHeaderDescriptor(name, out HeaderDescriptor descriptor) && Remove(descriptor); internal bool RemoveParsedValue(HeaderDescriptor descriptor, object value, bool removeAll = false) { diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs index 752926313ebe16..28317ffcd3bffb 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs @@ -498,6 +498,26 @@ public void InvalidHeaders_AddRequestAndResponseHeaders_Throw() Assert.Throws(() => { _headers.Add("Warning", "v"); }); } + [Fact] + public void Contains_DisallowedRequestHeaderOnContentHeaders_ReturnsFalse() + { + using var content = new StringContent("test"); + HttpContentHeaders headers = content.Headers; + Assert.False(headers.Contains("Accept")); + Assert.False(headers.Contains("Accept-Encoding")); + Assert.False(headers.Contains("Host")); + } + + [Fact] + public void Remove_DisallowedRequestHeaderOnContentHeaders_ReturnsFalse() + { + using var content = new StringContent("test"); + HttpContentHeaders headers = content.Headers; + Assert.False(headers.Remove("Accept")); + Assert.False(headers.Remove("Accept-Encoding")); + Assert.False(headers.Remove("Host")); + } + private sealed class ComputeLengthHttpContent : HttpContent { private readonly Func _tryComputeLength; diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs index 70615e7b8ad527..2970cad42c69ef 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs @@ -1069,29 +1069,21 @@ public void Clear_AddMultipleHeadersAndThenClear_NoHeadersInCollection() Assert.Equal(2, headers.Parser.TryParseValueCallCount); } - [Fact] - public void Remove_UseNullHeaderName_Throw() - { - MockHeaders headers = new MockHeaders(); - - AssertExtensions.Throws("name", () => { headers.Remove(null); }); - } - - [Fact] - public void Remove_UseEmptyHeaderName_Throw() + [Theory] + [InlineData(null)] + [InlineData("")] + public void Remove_UseNullOrEmptyHeaderName_ReturnsFalse(string? headerName) { MockHeaders headers = new MockHeaders(); - - AssertExtensions.Throws("name", () => { headers.Remove(""); }); + Assert.False(headers.Remove(headerName)); } [Theory] [MemberData(nameof(GetInvalidHeaderNames))] - public void Remove_UseInvalidHeaderName_Throw(string headerName) + public void Remove_UseInvalidHeaderName_ReturnsFalse(string headerName) { MockHeaders headers = new MockHeaders(); - - Assert.Throws(() => { headers.Remove(headerName); }); + Assert.False(headers.Remove(headerName)); } [Fact] @@ -1593,29 +1585,21 @@ public void NonValidated_ValidInvalidAndRaw_AllReturned() } } - [Fact] - public void Contains_UseNullHeaderName_Throw() - { - MockHeaders headers = new MockHeaders(); - - AssertExtensions.Throws("name", () => { headers.Contains(null); }); - } - - [Fact] - public void Contains_UseEmptyHeaderName_Throw() + [Theory] + [InlineData(null)] + [InlineData("")] + public void Contains_UseNullOrEmptyHeaderName_ReturnsFalse(string? headerName) { MockHeaders headers = new MockHeaders(); - - AssertExtensions.Throws("name", () => { headers.Contains(""); }); + Assert.False(headers.Contains(headerName)); } [Theory] [MemberData(nameof(GetInvalidHeaderNames))] - public void Contains_UseInvalidHeaderName_Throw(string headerName) + public void Contains_UseInvalidHeaderName_ReturnsFalse(string headerName) { MockHeaders headers = new MockHeaders(); - - Assert.Throws(() => { headers.Contains(headerName); }); + Assert.False(headers.Contains(headerName)); } [Fact] @@ -2549,10 +2533,10 @@ public async Task ConcurrentReads_ReturnTheSameParsedValues(bool useDictionary, } [Fact] - public void TryAddInvalidHeader_ShouldThrowFormatException() + public void Remove_InvalidHeaderName_ReturnsFalse() { MockHeaders headers = new MockHeaders(); - AssertExtensions.ThrowsContains(() => headers.Remove("\u0080"), "\u0080"); + Assert.False(headers.Remove("\u0080")); } [Theory] diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs index 926bd3ca3417c6..f12a5983455b77 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs @@ -1650,5 +1650,23 @@ public void InvalidHeaders_AddContentHeaders_Throw() Assert.Throws(() => { headers.Add("Expires", "v"); }); Assert.Throws(() => { headers.Add("Last-Modified", "v"); }); } + + [Fact] + public void Contains_DisallowedContentHeaderOnRequestHeaders_ReturnsFalse() + { + HttpRequestHeaders headers = new HttpRequestMessage().Headers; + Assert.False(headers.Contains("Content-Type")); + Assert.False(headers.Contains("Content-Encoding")); + Assert.False(headers.Contains("content-length")); + } + + [Fact] + public void Remove_DisallowedContentHeaderOnRequestHeaders_ReturnsFalse() + { + HttpRequestHeaders headers = new HttpRequestMessage().Headers; + Assert.False(headers.Remove("Content-Type")); + Assert.False(headers.Remove("Content-Encoding")); + Assert.False(headers.Remove("content-length")); + } } -} +} \ No newline at end of file From e7f120562845758295a92ac57665a7ea517efd0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:40:25 +0000 Subject: [PATCH 3/4] Add HttpResponseHeaders tests for Contains/Remove with disallowed headers and fix trailing newline Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/d0ce6ca6-9f52-4275-b304-1ea2502913cc Co-authored-by: MihaZupan <25307628+MihaZupan@users.noreply.github.com> --- .../Headers/HttpRequestHeadersTest.cs | 2 +- .../Headers/HttpResponseHeadersTest.cs | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs index f12a5983455b77..3d9723a3be48ca 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs @@ -1669,4 +1669,4 @@ public void Remove_DisallowedContentHeaderOnRequestHeaders_ReturnsFalse() Assert.False(headers.Remove("content-length")); } } -} \ No newline at end of file +} diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpResponseHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpResponseHeadersTest.cs index b0222a76bc6c25..141eb0bcf567df 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpResponseHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpResponseHeadersTest.cs @@ -710,5 +710,21 @@ public void InvalidHeaders_AddContentHeaders_Throw() Assert.Throws(() => { headers.Add("Expires", "v"); }); Assert.Throws(() => { headers.Add("Last-Modified", "v"); }); } + + [Fact] + public void Contains_DisallowedContentHeaderOnResponseHeaders_ReturnsFalse() + { + Assert.False(headers.Contains("Content-Type")); + Assert.False(headers.Contains("Content-Encoding")); + Assert.False(headers.Contains("content-length")); + } + + [Fact] + public void Remove_DisallowedContentHeaderOnResponseHeaders_ReturnsFalse() + { + Assert.False(headers.Remove("Content-Type")); + Assert.False(headers.Remove("Content-Encoding")); + Assert.False(headers.Remove("content-length")); + } } -} +} \ No newline at end of file From 3f8f83d375e4c14830779cfb9f271b1c6d371b03 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Mon, 20 Apr 2026 18:44:23 +0200 Subject: [PATCH 4/4] Style changes Co-authored-by: Miha Zupan --- .../src/System/Net/Http/Headers/HttpHeaders.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs index 4fc0236161ece5..f6dafc471ec871 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs @@ -309,7 +309,9 @@ internal bool TryGetValues(HeaderDescriptor descriptor, [NotNullWhen(true)] out return false; } - public bool Contains(string name) => TryGetHeaderDescriptor(name, out HeaderDescriptor descriptor) && Contains(descriptor); + public bool Contains(string name) => + TryGetHeaderDescriptor(name, out HeaderDescriptor descriptor) && + Contains(descriptor); public override string ToString() { @@ -478,7 +480,9 @@ internal void SetOrRemoveParsedValue(HeaderDescriptor descriptor, object? value) } } - public bool Remove(string name) => TryGetHeaderDescriptor(name, out HeaderDescriptor descriptor) && Remove(descriptor); + public bool Remove(string name) => + TryGetHeaderDescriptor(name, out HeaderDescriptor descriptor) && + Remove(descriptor); internal bool RemoveParsedValue(HeaderDescriptor descriptor, object value, bool removeAll = false) {