Skip to content

Commit 822cb27

Browse files
authored
Validate injected header values in DiagnosticsHandler (#117884)
1 parent 69ee700 commit 822cb27

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,14 @@ private void InjectHeaders(Activity currentActivity, HttpRequestMessage request)
356356
{
357357
_propagator.Inject(currentActivity, request, static (carrier, key, value) =>
358358
{
359-
if (carrier is HttpRequestMessage request &&
360-
key is not null &&
361-
HeaderDescriptor.TryGet(key, out HeaderDescriptor descriptor) &&
362-
!request.Headers.TryGetHeaderValue(descriptor, out _))
359+
if (carrier is HttpRequestMessage request && key is not null)
363360
{
364-
request.Headers.TryAddWithoutValidation(descriptor, value);
361+
HeaderDescriptor descriptor = request.Headers.GetHeaderDescriptor(key);
362+
363+
if (!request.Headers.Contains(descriptor))
364+
{
365+
request.Headers.Add(descriptor, value);
366+
}
365367
}
366368
});
367369
request.MarkPropagatorStateInjectedByDiagnosticsHandler();

src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,7 @@ private static void ParseAndAddValue(HeaderDescriptor descriptor, HeaderStoreIte
11311131
}
11321132
}
11331133

1134-
private HeaderDescriptor GetHeaderDescriptor(string name)
1134+
internal HeaderDescriptor GetHeaderDescriptor(string name)
11351135
{
11361136
ArgumentException.ThrowIfNullOrEmpty(name);
11371137

src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,27 @@ await GetFactoryForVersion(UseVersion).CreateClientAndServerAsync(
14061406
});
14071407
}
14081408

1409+
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
1410+
[InlineData("A B", "Foo", typeof(FormatException))] // Invalid header name
1411+
[InlineData("Content-Length", "42", typeof(InvalidOperationException))] // Invalid header name for the request headers collection
1412+
[InlineData("Foo", "Bar\nBaz", typeof(FormatException))] // Invalid header value
1413+
public async Task SendAsync_PropagatorInjectsInvalidHeaders_Throws(string headerName, string headerValue, Type exceptionType)
1414+
{
1415+
using Activity parent = new Activity("parent");
1416+
parent.SetIdFormat(ActivityIdFormat.W3C);
1417+
parent.Start();
1418+
1419+
using var handler = CreateSocketsHttpHandler(allowAllCertificates: true);
1420+
handler.ActivityHeadersPropagator = new DelegatingPropagator([headerName], (activity, carrier, setter) => setter(carrier, headerName, headerValue));
1421+
1422+
using var client = new HttpClient(handler);
1423+
1424+
// Url doesn't matter since the request should fail before hitting the network.
1425+
var request = CreateRequest(HttpMethod.Get, new Uri("https://microsoft.com"), UseVersion, exactVersion: true);
1426+
1427+
await Assert.ThrowsAsync(exceptionType, () => client.SendAsync(TestAsync, request));
1428+
}
1429+
14091430
public static IEnumerable<object[]> SocketsHttpHandler_ActivityCreation_MemberData()
14101431
{
14111432
foreach (var currentActivitySet in new bool[] {
@@ -1855,5 +1876,20 @@ private static void AssertHeadersAreInjected(HttpRequestData request, Activity p
18551876
var request = CreateRequest(HttpMethod.Get, uri, Version.Parse(useVersion), exactVersion: true);
18561877
return (request, await client.SendAsync(bool.Parse(testAsync), request, cancellationToken));
18571878
}
1879+
1880+
private sealed class DelegatingPropagator(string[] fields, Action<Activity?, object?, DistributedContextPropagator.PropagatorSetterCallback?> inject) : DistributedContextPropagator
1881+
{
1882+
public override IReadOnlyCollection<string> Fields => fields;
1883+
1884+
public override IEnumerable<KeyValuePair<string, string?>>? ExtractBaggage(object? carrier, PropagatorGetterCallback? getter) => [];
1885+
1886+
public override void ExtractTraceIdAndState(object? carrier, PropagatorGetterCallback? getter, out string? traceId, out string? traceState)
1887+
{
1888+
traceId = null;
1889+
traceState = null;
1890+
}
1891+
1892+
public override void Inject(Activity? activity, object? carrier, PropagatorSetterCallback? setter) => inject(activity, carrier, setter);
1893+
}
18581894
}
18591895
}

0 commit comments

Comments
 (0)