CVE-2024-32028
Description
OpenTelemetry dotnet is a dotnet telemetry framework. In affected versions of OpenTelemetry.Instrumentation.Http and OpenTelemetry.Instrumentation.AspNetCore the url.full writes attribute/tag on spans (Activity) when tracing is enabled for outgoing http requests and OpenTelemetry.Instrumentation.AspNetCore writes the url.query attribute/tag on spans (Activity) when tracing is enabled for incoming http requests. These attributes are defined by the Semantic Conventions for HTTP Spans. Up until version 1.8.1 the values written by OpenTelemetry.Instrumentation.Http & OpenTelemetry.Instrumentation.AspNetCore will pass-through the raw query string as was sent or received (respectively). This may lead to sensitive information (e.g. EUII - End User Identifiable Information, credentials, etc.) being leaked into telemetry backends (depending on the application(s) being instrumented) which could cause privacy and/or security incidents. Note: Older versions of OpenTelemetry.Instrumentation.Http & OpenTelemetry.Instrumentation.AspNetCore may use different tag names but have the same vulnerability. The 1.8.1 versions of OpenTelemetry.Instrumentation.Http & OpenTelemetry.Instrumentation.AspNetCore will now redact by default all values detected on transmitted or received query strings. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
OpenTelemetry.Instrumentation.HttpNuGet | < 1.8.1 | 1.8.1 |
OpenTelemetry.Instrumentation.AspNetCoreNuGet | < 1.8.1 | 1.8.1 |
Patches
1e222ecb5942d[Instrumentation.Http][Instrumentation.AspNetCore] Fix `url.full` and `url.query` attribute values (#5532)
22 files changed · +359 −15
OpenTelemetry.sln+1 −0 modified@@ -270,6 +270,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A49299 src\Shared\PeerServiceResolver.cs = src\Shared\PeerServiceResolver.cs src\Shared\PeriodicExportingMetricReaderHelper.cs = src\Shared\PeriodicExportingMetricReaderHelper.cs src\Shared\PooledList.cs = src\Shared\PooledList.cs + src\Shared\RedactionHelper.cs = src\Shared\RedactionHelper.cs src\Shared\RequestMethodHelper.cs = src\Shared\RequestMethodHelper.cs src\Shared\ResourceSemanticConventions.cs = src\Shared\ResourceSemanticConventions.cs src\Shared\SemanticConventions.cs = src\Shared\SemanticConventions.cs
src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreTraceInstrumentationOptions.cs+18 −0 modified@@ -32,6 +32,14 @@ internal AspNetCoreTraceInstrumentationOptions(IConfiguration configuration) { this.EnableGrpcAspNetCoreSupport = enableGrpcInstrumentation; } + + if (configuration.TryGetBoolValue( + AspNetCoreInstrumentationEventSource.Log, + "OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION", + out var disableUrlQueryRedaction)) + { + this.DisableUrlQueryRedaction = disableUrlQueryRedaction; + } } /// <summary> @@ -94,4 +102,14 @@ internal AspNetCoreTraceInstrumentationOptions(IConfiguration configuration) /// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/rpc/rpc-spans.md. /// </remarks> internal bool EnableGrpcAspNetCoreSupport { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether the url query value should be redacted or not. + /// </summary> + /// <remarks> + /// The query parameter values are redacted with value set as Redacted. + /// e.g. `?key1=value1` is set as `?key1=Redacted`. + /// The redaction can be disabled by setting this property to <see langword="true" />. + /// </remarks> + internal bool DisableUrlQueryRedaction { get; set; } }
src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md+11 −1 modified@@ -1,6 +1,16 @@ # Changelog -## Unreleased +## 1.8.1 + +Released 2024-Apr-12 + +* **Breaking Change**: Fixed tracing instrumentation so that by default any + values detected in the query string component of requests are replaced with + the text `Redacted` when building the `url.query` tag. For example, + `?key1=value1&key2=value2` becomes `?key1=Redacted&key2=Redacted`. You can + disable this redaction by setting the environment variable + `OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION` to `true`. + ([#5532](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5532)) ## 1.8.0
src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInListener.cs+8 −2 modified@@ -193,8 +193,14 @@ public void OnStartActivity(Activity activity, object payload) if (request.QueryString.HasValue) { - // QueryString should be sanitized. see: https://github.com/open-telemetry/opentelemetry-dotnet/issues/4571 - activity.SetTag(SemanticConventions.AttributeUrlQuery, request.QueryString.Value); + if (this.options.DisableUrlQueryRedaction) + { + activity.SetTag(SemanticConventions.AttributeUrlQuery, request.QueryString.Value); + } + else + { + activity.SetTag(SemanticConventions.AttributeUrlQuery, RedactionHelper.GetRedactedQueryString(request.QueryString.Value)); + } } RequestMethodHelper.SetHttpMethodTag(activity, request.Method);
src/OpenTelemetry.Instrumentation.AspNetCore/OpenTelemetry.Instrumentation.AspNetCore.csproj+1 −0 modified@@ -17,6 +17,7 @@ <Compile Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.GrpcNetClient\GrpcTagHelper.cs" Link="Includes\GrpcTagHelper.cs" /> <Compile Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.GrpcNetClient\StatusCanonicalCode.cs" Link="Includes\StatusCanonicalCode.cs" /> <Compile Include="$(RepoRoot)\src\Shared\Guard.cs" Link="Includes\Guard.cs" /> + <Compile Include="$(RepoRoot)\src\Shared\RedactionHelper.cs" Link="Includes\RedactionHelper.cs" /> <Compile Include="$(RepoRoot)\src\Shared\RequestMethodHelper.cs" Link="Includes\RequestMethodHelper.cs" /> <Compile Include="$(RepoRoot)\src\Shared\Shims\NullableAttributes.cs" Link="Includes\Shims\NullableAttributes.cs" /> <Compile Include="$(RepoRoot)\src\Shared\Options\*.cs" Link="Includes\Options\%(Filename).cs" />
src/OpenTelemetry.Instrumentation.AspNetCore/README.md+5 −1 modified@@ -75,7 +75,11 @@ for more details about each individual attribute: * `server.address` * `server.port` * `url.path` -* `url.query` +* `url.query` - By default, the values in the query component are replaced with + the text `Redacted`. For example, `?key1=value1&key2=value2` becomes + `?key1=Redacted&key2=Redacted`. You can disable this redaction by setting the + environment variable + `OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION` to `true`. * `url.scheme` [Enrich Api](#enrich) can be used if any additional attributes are
src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md+11 −1 modified@@ -1,6 +1,16 @@ # Changelog -## Unreleased +## 1.8.1 + +Released 2024-Apr-12 + +* **Breaking Change**: Fixed tracing instrumentation so that by default any + values detected in the query string component of requests are replaced with + the text `Redacted` when building the `url.full` tag. For example, + `?key1=value1&key2=value2` becomes `?key1=Redacted&key2=Redacted`. You can + disable this redaction by setting the environment variable + `OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION` to `true`. + ([#5532](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5532)) ## 1.8.0
src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentationTracerProviderBuilderExtensions.cs+2 −0 modified@@ -59,6 +59,8 @@ public static TracerProviderBuilder AddHttpClientInstrumentation( { services.Configure(name, configureHttpClientTraceInstrumentationOptions); } + + services.RegisterOptionsFactory(configuration => new HttpClientTraceInstrumentationOptions(configuration)); }); #if NETFRAMEWORK
src/OpenTelemetry.Instrumentation.Http/HttpClientTraceInstrumentationOptions.cs+33 −1 modified@@ -3,10 +3,11 @@ using System.Diagnostics; using System.Net; +using System.Runtime.CompilerServices; #if NETFRAMEWORK using System.Net.Http; #endif -using System.Runtime.CompilerServices; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Instrumentation.Http.Implementation; namespace OpenTelemetry.Instrumentation.Http; @@ -16,6 +17,27 @@ namespace OpenTelemetry.Instrumentation.Http; /// </summary> public class HttpClientTraceInstrumentationOptions { + /// <summary> + /// Initializes a new instance of the <see cref="HttpClientTraceInstrumentationOptions"/> class. + /// </summary> + public HttpClientTraceInstrumentationOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) + { + } + + internal HttpClientTraceInstrumentationOptions(IConfiguration configuration) + { + Debug.Assert(configuration != null, "configuration was null"); + + if (configuration.TryGetBoolValue( + HttpInstrumentationEventSource.Log, + "OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION", + out var disableUrlQueryRedaction)) + { + this.DisableUrlQueryRedaction = disableUrlQueryRedaction; + } + } + /// <summary> /// Gets or sets a filter function that determines whether or not to /// collect telemetry on a per request basis. @@ -125,6 +147,16 @@ public class HttpClientTraceInstrumentationOptions /// </remarks> public bool RecordException { get; set; } + /// <summary> + /// Gets or sets a value indicating whether the url query value should be redacted or not. + /// </summary> + /// <remarks> + /// The query parameter values are redacted with value set as Redacted. + /// e.g. `?key1=value1` is set as `?key1=Redacted`. + /// The redaction can be disabled by setting this property to <see langword="true" />. + /// </remarks> + internal bool DisableUrlQueryRedaction { get; set; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool EventFilterHttpRequestMessage(string activityName, object arg1) {
src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerDiagnosticListener.cs+1 −1 modified@@ -149,7 +149,7 @@ public void OnStartActivity(Activity activity, object payload) activity.SetTag(SemanticConventions.AttributeServerAddress, request.RequestUri.Host); activity.SetTag(SemanticConventions.AttributeServerPort, request.RequestUri.Port); - activity.SetTag(SemanticConventions.AttributeUrlFull, HttpTagHelper.GetUriTagValueFromRequestUri(request.RequestUri)); + activity.SetTag(SemanticConventions.AttributeUrlFull, HttpTagHelper.GetUriTagValueFromRequestUri(request.RequestUri, this.options.DisableUrlQueryRedaction)); try {
src/OpenTelemetry.Instrumentation.Http/Implementation/HttpInstrumentationEventSource.cs+13 −1 modified@@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 using System.Diagnostics.Tracing; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; namespace OpenTelemetry.Instrumentation.Http.Implementation; @@ -10,7 +11,7 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation; /// EventSource events emitted from the project. /// </summary> [EventSource(Name = "OpenTelemetry-Instrumentation-Http")] -internal sealed class HttpInstrumentationEventSource : EventSource +internal sealed class HttpInstrumentationEventSource : EventSource, IConfigurationExtensionsLogger { public static HttpInstrumentationEventSource Log = new(); @@ -100,4 +101,15 @@ public void UnknownErrorProcessingEvent(string handlerName, string eventName, st { this.WriteEvent(7, handlerName, eventName, ex); } + + [Event(8, Message = "Configuration key '{0}' has an invalid value: '{1}'", Level = EventLevel.Warning)] + public void InvalidConfigurationValue(string key, string value) + { + this.WriteEvent(8, key, value); + } + + void IConfigurationExtensionsLogger.LogInvalidConfigurationValue(string key, string value) + { + this.InvalidConfigurationValue(key, value); + } }
src/OpenTelemetry.Instrumentation.Http/Implementation/HttpTagHelper.cs+8 −3 modified@@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using OpenTelemetry.Internal; + namespace OpenTelemetry.Instrumentation.Http.Implementation; /// <summary> @@ -12,15 +14,18 @@ internal static class HttpTagHelper /// Gets the OpenTelemetry standard uri tag value for a span based on its request <see cref="Uri"/>. /// </summary> /// <param name="uri"><see cref="Uri"/>.</param> + /// <param name="disableQueryRedaction">Indicates whether query parameter should be redacted or not.</param> /// <returns>Span uri value.</returns> - public static string GetUriTagValueFromRequestUri(Uri uri) + public static string GetUriTagValueFromRequestUri(Uri uri, bool disableQueryRedaction) { - if (string.IsNullOrEmpty(uri.UserInfo)) + if (string.IsNullOrEmpty(uri.UserInfo) && disableQueryRedaction) { return uri.OriginalString; } - return string.Concat(uri.Scheme, Uri.SchemeDelimiter, uri.Authority, uri.PathAndQuery, uri.Fragment); + var query = disableQueryRedaction ? uri.Query : RedactionHelper.GetRedactedQueryString(uri.Query); + + return string.Concat(uri.Scheme, Uri.SchemeDelimiter, uri.Authority, uri.AbsolutePath, query, uri.Fragment); } public static string GetProtocolVersionString(Version httpVersion) => (httpVersion.Major, httpVersion.Minor) switch
src/OpenTelemetry.Instrumentation.Http/Implementation/HttpWebRequestActivitySource.netfx.cs+1 −1 modified@@ -105,7 +105,7 @@ private static void AddRequestTagsAndInstrumentRequest(HttpWebRequest request, A activity.SetTag(SemanticConventions.AttributeServerAddress, request.RequestUri.Host); activity.SetTag(SemanticConventions.AttributeServerPort, request.RequestUri.Port); - activity.SetTag(SemanticConventions.AttributeUrlFull, HttpTagHelper.GetUriTagValueFromRequestUri(request.RequestUri)); + activity.SetTag(SemanticConventions.AttributeUrlFull, HttpTagHelper.GetUriTagValueFromRequestUri(request.RequestUri, tracingOptions.DisableUrlQueryRedaction)); try {
src/OpenTelemetry.Instrumentation.Http/OpenTelemetry.Instrumentation.Http.csproj+5 −0 modified@@ -12,8 +12,12 @@ </PropertyGroup> <ItemGroup> + <Compile Include="$(RepoRoot)\src\Shared\Configuration\*.cs" Link="Includes\Configuration\%(Filename).cs" /> + <Compile Include="$(RepoRoot)\src\Shared\EnvironmentVariables\*.cs" Link="Includes\EnvironmentVariables\%(Filename).cs" /> <Compile Include="$(RepoRoot)\src\Shared\Guard.cs" Link="Includes\Guard.cs" /> <Compile Include="$(RepoRoot)\src\Shared\Shims\NullableAttributes.cs" Link="Includes\Shims\NullableAttributes.cs" /> + <Compile Include="$(RepoRoot)\src\Shared\Options\*.cs" Link="Includes\Options\%(Filename).cs" /> + <Compile Include="$(RepoRoot)\src\Shared\RedactionHelper.cs" Link="Includes\RedactionHelper.cs" /> <Compile Include="$(RepoRoot)\src\Shared\RequestMethodHelper.cs" Link="Includes\RequestMethodHelper.cs" /> </ItemGroup> @@ -29,6 +33,7 @@ <ItemGroup> <Reference Include="System.Net.Http" Condition="'$(TargetFramework)' == '$(NetFrameworkMinimumSupportedVersion)'" /> <PackageReference Include="Microsoft.Extensions.Options" /> + <PackageReference Include="Microsoft.Extensions.Configuration" /> </ItemGroup> </Project>
src/OpenTelemetry.Instrumentation.Http/README.md+5 −1 modified@@ -68,7 +68,11 @@ for more details about each individual attribute: * `network.protocol.version` * `server.address` * `server.port` -* `url.full` +* `url.full` - By default, the values in the query component of the url are + replaced with the text `Redacted`. For example, `?key1=value1&key2=value2` + becomes `?key1=Redacted&key2=Redacted`. You can disable this redaction by + setting the environment variable + `OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION` to `true`. [Enrich Api](#enrich-httpclient-api) can be used if any additional attributes are required on activity.
src/Shared/RedactionHelper.cs+59 −0 added@@ -0,0 +1,59 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#nullable enable + +using System.Text; + +namespace OpenTelemetry.Internal; + +internal class RedactionHelper +{ + private static readonly string RedactedText = "Redacted"; + + public static string? GetRedactedQueryString(string query) + { + int length = query.Length; + int index = 0; + + // Preallocate some size to avoid re-sizing multiple times. + // Since the size will increase, allocating twice as much. + // TODO: Check to see if we can borrow from https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/Text/ValueStringBuilder.cs + // to improve perf. + StringBuilder queryBuilder = new(2 * length); + while (index < query.Length) + { + // Check if the character is = for redacting value. + if (query[index] == '=') + { + // Append = + queryBuilder.Append('='); + index++; + + // Append redactedText in place of original value. + queryBuilder.Append(RedactedText); + + // Move until end of this key/value pair. + while (index < length && query[index] != '&') + { + index++; + } + + // End of key/value. + if (index < length && query[index] == '&') + { + queryBuilder.Append(query[index]); + } + } + else + { + // Keep adding to the result + queryBuilder.Append(query[index]); + } + + index++; + } + + return queryBuilder.ToString(); + } +}
test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs+73 −0 modified@@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -1052,6 +1053,78 @@ public async Task NoSiblingActivityCreatedWhenTraceFlagsNone() } #endif + [Theory] + [InlineData("?a", "?a", false)] + [InlineData("?a=bdjdjh", "?a=Redacted", false)] + [InlineData("?a=b&", "?a=Redacted&", false)] + [InlineData("?c=b&", "?c=Redacted&", false)] + [InlineData("?c=a", "?c=Redacted", false)] + [InlineData("?a=b&c", "?a=Redacted&c", false)] + [InlineData("?a=b&c=1123456&", "?a=Redacted&c=Redacted&", false)] + [InlineData("?a=b&c=1&a1", "?a=Redacted&c=Redacted&a1", false)] + [InlineData("?a=ghgjgj&c=1deedd&a1=", "?a=Redacted&c=Redacted&a1=Redacted", false)] + [InlineData("?a=b&c=11&a1=&", "?a=Redacted&c=Redacted&a1=Redacted&", false)] + [InlineData("?c&c&c&", "?c&c&c&", false)] + [InlineData("?a&a&a&a", "?a&a&a&a", false)] + [InlineData("?&&&&&&&", "?&&&&&&&", false)] + [InlineData("?c", "?c", false)] + [InlineData("?a", "?a", true)] + [InlineData("?a=bdfdfdf", "?a=bdfdfdf", true)] + [InlineData("?a=b&", "?a=b&", true)] + [InlineData("?c=b&", "?c=b&", true)] + [InlineData("?c=a", "?c=a", true)] + [InlineData("?a=b&c", "?a=b&c", true)] + [InlineData("?a=b&c=111111&", "?a=b&c=111111&", true)] + [InlineData("?a=b&c=1&a1", "?a=b&c=1&a1", true)] + [InlineData("?a=b&c=1&a1=", "?a=b&c=1&a1=", true)] + [InlineData("?a=b123&c=11&a1=&", "?a=b123&c=11&a1=&", true)] + [InlineData("?c&c&c&", "?c&c&c&", true)] + [InlineData("?a&a&a&a", "?a&a&a&a", true)] + [InlineData("?&&&&&&&", "?&&&&&&&", true)] + [InlineData("?c", "?c", true)] + [InlineData("?c=%26&", "?c=Redacted&", false)] + public async Task ValidateUrlQueryRedaction(string urlQuery, string expectedUrlQuery, bool disableQueryRedaction) + { + var exportedItems = new List<Activity>(); + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary<string, string> { ["OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION"] = disableQueryRedaction.ToString() }) + .Build(); + + var path = "/api/values" + urlQuery; + + // Arrange + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .ConfigureServices(services => services.AddSingleton<IConfiguration>(configuration)) + .AddAspNetCoreInstrumentation() + .AddInMemoryExporter(exportedItems) + .Build(); + + using (var client = this.factory + .WithWebHostBuilder(builder => + { + builder.ConfigureLogging(loggingBuilder => loggingBuilder.ClearProviders()); + }) + .CreateClient()) + { + try + { + using var response = await client.GetAsync(path); + } + catch (Exception) + { + // ignore errors + } + + WaitForActivityExport(exportedItems, 1); + } + + Assert.Single(exportedItems); + var activity = exportedItems[0]; + + Assert.Equal(expectedUrlQuery, activity.GetTagValue(SemanticConventions.AttributeUrlQuery)); + } + public void Dispose() { this.tracerProvider?.Dispose();
test/OpenTelemetry.Instrumentation.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs+5 −2 modified@@ -27,7 +27,7 @@ public IncomingRequestsCollectionsIsAccordingToTheSpecTests(WebApplicationFactor [Theory] [InlineData("/api/values", null, "user-agent", 200, null)] - [InlineData("/api/values", "?query=1", null, 200, null)] + [InlineData("/api/values", null, null, 200, null)] [InlineData("/api/exception", null, null, 503, null)] [InlineData("/api/exception", null, null, 503, null, true)] public async Task SuccessfulTemplateControllerCallGeneratesASpan_New( @@ -49,7 +49,10 @@ public async Task SuccessfulTemplateControllerCallGeneratesASpan_New( services.AddSingleton<CallbackMiddleware.CallbackMiddlewareImpl>(new TestCallbackMiddlewareImpl(statusCode, reasonPhrase)); services.AddOpenTelemetry() .WithTracing(builder => builder - .AddAspNetCoreInstrumentation(options => options.RecordException = recordException) + .AddAspNetCoreInstrumentation(options => + { + options.RecordException = recordException; + }) .AddInMemoryExporter(exportedItems)); }); builder.ConfigureLogging(loggingBuilder => loggingBuilder.ClearProviders());
test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs+64 −0 modified@@ -2,8 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 using System.Diagnostics; +using Microsoft.Extensions.Configuration; + #if NETFRAMEWORK using System.Net.Http; + #endif using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Context.Propagation; @@ -666,6 +669,67 @@ public async Task DoesNotReportExceptionEventOnErrorResponseWithGetStringAsync() Assert.Empty(exportedItems[0].Events); } + [Theory] + [InlineData("?a", "?a", false)] + [InlineData("?a=bdjdjh", "?a=Redacted", false)] + [InlineData("?a=b&", "?a=Redacted&", false)] + [InlineData("?c=b&", "?c=Redacted&", false)] + [InlineData("?c=a", "?c=Redacted", false)] + [InlineData("?a=b&c", "?a=Redacted&c", false)] + [InlineData("?a=b&c=1123456&", "?a=Redacted&c=Redacted&", false)] + [InlineData("?a=b&c=1&a1", "?a=Redacted&c=Redacted&a1", false)] + [InlineData("?a=ghgjgj&c=1deedd&a1=", "?a=Redacted&c=Redacted&a1=Redacted", false)] + [InlineData("?a=b&c=11&a1=&", "?a=Redacted&c=Redacted&a1=Redacted&", false)] + [InlineData("?c&c&c&", "?c&c&c&", false)] + [InlineData("?a&a&a&a", "?a&a&a&a", false)] + [InlineData("?&&&&&&&", "?&&&&&&&", false)] + [InlineData("?c", "?c", false)] + [InlineData("?a", "?a", true)] + [InlineData("?a=bdfdfdf", "?a=bdfdfdf", true)] + [InlineData("?a=b&", "?a=b&", true)] + [InlineData("?c=b&", "?c=b&", true)] + [InlineData("?c=a", "?c=a", true)] + [InlineData("?a=b&c", "?a=b&c", true)] + [InlineData("?a=b&c=111111&", "?a=b&c=111111&", true)] + [InlineData("?a=b&c=1&a1", "?a=b&c=1&a1", true)] + [InlineData("?a=b&c=1&a1=", "?a=b&c=1&a1=", true)] + [InlineData("?a=b123&c=11&a1=&", "?a=b123&c=11&a1=&", true)] + [InlineData("?c&c&c&", "?c&c&c&", true)] + [InlineData("?a&a&a&a", "?a&a&a&a", true)] + [InlineData("?&&&&&&&", "?&&&&&&&", true)] + [InlineData("?c", "?c", true)] + [InlineData("?c=%26&", "?c=Redacted&", false)] + public async Task ValidateUrlQueryRedaction(string urlQuery, string expectedUrlQuery, bool disableQueryRedaction) + { + var exportedItems = new List<Activity>(); + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary<string, string> { ["OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION"] = disableQueryRedaction.ToString() }) + .Build(); + + // Arrange + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .ConfigureServices(services => services.AddSingleton<IConfiguration>(configuration)) + .AddHttpClientInstrumentation() + .AddInMemoryExporter(exportedItems) + .Build(); + + using var c = new HttpClient(); + try + { + await c.GetStringAsync($"{this.url}path{urlQuery}"); + } + catch + { + } + + Assert.Single(exportedItems); + var activity = exportedItems[0]; + + var expectedUrl = $"{this.url}path{expectedUrlQuery}"; + Assert.Equal(expectedUrl, activity.GetTagValue(SemanticConventions.AttributeUrlFull)); + } + [Theory] [InlineData(true, true)] [InlineData(true, false)]
test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestActivitySourceTests.netfx.cs+2 −0 modified@@ -35,6 +35,8 @@ static HttpWebRequestActivitySourceTests() ValidateBaggage(httpWebRequest); } }, + + DisableUrlQueryRedaction = true, }; HttpWebRequestActivitySource.TracingOptions = options;
test/OpenTelemetry.Tests/Internal/RedactionHelperTest.cs+32 −0 added@@ -0,0 +1,32 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry.Internal; +using Xunit; + +namespace OpenTelemetry.Tests.Internal; + +public class RedactionHelperTest +{ + [Theory] + [InlineData("?a", "?a")] + [InlineData("?a=b", "?a=Redacted")] + [InlineData("?a=b&", "?a=Redacted&")] + [InlineData("?c=b&", "?c=Redacted&")] + [InlineData("?c=a", "?c=Redacted")] + [InlineData("?a=b&c", "?a=Redacted&c")] + [InlineData("?a=b&c=1&", "?a=Redacted&c=Redacted&")] + [InlineData("?a=b&c=1&a1", "?a=Redacted&c=Redacted&a1")] + [InlineData("?a=b&c=1&a1=", "?a=Redacted&c=Redacted&a1=Redacted")] + [InlineData("?a=b&c=11&a1=&", "?a=Redacted&c=Redacted&a1=Redacted&")] + [InlineData("?c&c&c&", "?c&c&c&")] + [InlineData("?a&a&a&a", "?a&a&a&a")] + [InlineData("?&&&&&&&", "?&&&&&&&")] + [InlineData("?c", "?c")] + [InlineData("?=c", "?=Redacted")] + [InlineData("?=c&=", "?=Redacted&=Redacted")] + public void QueryStringIsRedacted(string input, string expected) + { + Assert.Equal(expected, RedactionHelper.GetRedactedQueryString(input)); + } +}
test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj+1 −0 modified@@ -24,6 +24,7 @@ <Compile Include="$(RepoRoot)\src\Shared\DiagnosticSourceInstrumentation\PropertyFetcher.cs" Link="Includes\PropertyFetcher.cs" /> <Compile Include="$(RepoRoot)\src\Shared\Metrics\Base2ExponentialBucketHistogramHelper.cs" Link="Includes\Metrics\Base2ExponentialBucketHistogramHelper.cs" /> <Compile Include="$(RepoRoot)\src\Shared\PeriodicExportingMetricReaderHelper.cs" Link="Includes\PeriodicExportingMetricReaderHelper.cs" /> + <Compile Include="$(RepoRoot)\src\Shared\RedactionHelper.cs" Link="Includes\RedactionHelper.cs" /> <Compile Include="$(RepoRoot)\src\Shared\PooledList.cs" Link="Includes\PooledList.cs" /> <Compile Include="$(RepoRoot)\src\Shared\TagTransformerJsonHelper.cs" Link="Includes\TagTransformerJsonHelper.cs" /> </ItemGroup>
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-vh2m-22xx-q94fghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-32028ghsaADVISORY
- github.com/open-telemetry/opentelemetry-dotnet/commit/e222ecb5942d4ce1cadfd4306c39e3f4933a5c42nvdWEB
- github.com/open-telemetry/opentelemetry-dotnet/security/advisories/GHSA-vh2m-22xx-q94fnvdWEB
- github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.mdnvdWEB
News mentions
0No linked articles in our index yet.