Apr 23, 2026·6 min read·4 visits
OpenTelemetry .NET SDK versions up to 1.15.2 are vulnerable to a Denial of Service (DoS) attack via unauthenticated memory exhaustion (CWE-789). Maliciously crafted propagation headers force eager memory allocations, causing high garbage collection pressure. Patch to version 1.15.3 to resolve the issue.
The OpenTelemetry .NET SDK contains a denial of service vulnerability due to excessive memory allocation during the parsing of propagation headers. Vulnerable versions utilize eager allocation strategies, specifically `string.Split()`, to process Baggage, B3, and Jaeger headers. Unauthenticated remote attackers can exploit this by submitting crafted headers containing dense sequences of delimiters, forcing the application to allocate thousands of objects per request. This results in severe garbage collection pressure and potential OutOfMemoryException conditions. The vulnerability is fixed in version 1.15.3.
The OpenTelemetry .NET SDK provides instrumentation for distributed tracing, metrics, and logging. A core component of distributed tracing is context propagation, which ensures trace IDs, span IDs, and custom metadata (Baggage) are passed across service boundaries. The SDK extracts this context from incoming HTTP requests by reading standard propagation headers, including Baggage, B3, and Jaeger headers.
CVE-2026-40894 describes an allocation amplification vulnerability within the header parsing logic of OpenTelemetry.Api and OpenTelemetry.Extensions.Propagators. The vulnerability is classified under CWE-789 (Memory Allocation with Excessive Size Value). When the SDK processes incoming propagation headers, it employs an eager allocation strategy that scales linearly with the number of delimiter characters present in the header string, regardless of the actual data content.
An attacker with network access to an exposed service running the vulnerable OpenTelemetry .NET SDK can trigger this vulnerability by sending HTTP requests with intentionally malformed context headers. Because context propagation operates early in the ASP.NET Core request pipeline—often before authentication or application-level routing—this vulnerability is exploitable without credentials and affects the entire application surface area.
The fundamental flaw lies in the BaggagePropagator, B3Propagator, and JaegerPropagator classes, which utilized string.Split() to separate key-value pairs and list items. This method parses the entire input string immediately, creating an intermediate array of strings and allocating memory for each resulting substring. This pattern occurs before the SDK validates the total length of the header or the number of items it contains.
In the .NET memory model, each string allocation incurs overhead. A header payload of 8,192 bytes consisting entirely of comma delimiters (,) will instruct string.Split(',') to allocate an array capable of holding 8,193 references, followed by the instantiation of 8,193 empty string objects on the managed heap. The memory consumed by these objects significantly exceeds the original 8-kilobyte footprint of the header string.
Furthermore, a logic flaw in BaggagePropagator.Inject<T>() bypassed the standard 8,192-character limit if the baggage collection contained exactly one item. This allowed an application processing a malicious payload to serialize and propagate an oversized header to downstream microservices. This cascading effect broadens the denial-of-service condition across the internal service mesh.
The unpatched implementation relied on framework methods that generated managed allocations per delimiter. The fix, introduced in PR #7061, fundamentally alters the string processing model by replacing string.Split with manual parsing utilizing ReadOnlySpan<char>. The use of Span<T> allows the SDK to view and traverse segments of the original header string without duplicating memory.
The updated B3Propagator utilizes a custom ReadNextPart function. This function iterates through the header string using pointer arithmetic conceptually, isolating segments of the string sequentially.
// Refactored logic in B3Propagator.cs introduced in v1.15.3
private static ReadOnlySpan<char> ReadNextPart(ReadOnlySpan<char> header, int position, out int nextPosition)
{
var remaining = header.Slice(position);
var separatorIndex = remaining.IndexOf(XB3CombinedDelimiter);
if (separatorIndex < 0)
{
nextPosition = header.Length;
return remaining;
}
var result = remaining.Slice(0, separatorIndex);
nextPosition = position + separatorIndex + 1;
return result;
}This refactored logic operates entirely without heap allocations. Slice and IndexOf execute quickly over the contiguous memory area of the original string. Additionally, the patch introduces strict limit enforcement during the iteration phase. The parser actively tracks the item count and halts processing immediately if the 180-item limit or the 8,192-character limit is exceeded, neutralizing the allocation amplification vector.
Exploitation of CVE-2026-40894 requires an attacker to repeatedly submit HTTP requests containing crafted headers. The payload consists of standard HTTP headers targeting the OpenTelemetry extraction keys, such as baggage or b3. The value of the header is constructed entirely of delimiter characters.
A single HTTP request carrying baggage: ,,,,,[...5000 commas...] triggers the immediate allocation of thousands of string objects in Generation 0 of the .NET Garbage Collector. While Gen 0 collections are fast, sustained concurrent requests rapidly exhaust Gen 0 capacity. This forces the runtime to promote objects to Generation 1 and Generation 2.
When Generation 2 collections are triggered frequently, the .NET runtime suspends application execution (a "stop-the-world" pause) to compact the heap. This CPU-intensive process blocks thread execution, resulting in severe latency degradation. If the incoming request rate exceeds the garbage collector's ability to free memory, the application will throw an OutOfMemoryException and terminate.
The patch cycle that resolved CVE-2026-40894 also addressed related resource management vulnerabilities in the SDK. In PR #7064, the GrpcStatusDeserializer within OpenTelemetry.Exporter.OpenTelemetryProtocol was modified. The deserializer previously trusted the length prefix (Varint) of incoming GRPC status messages, allocating byte arrays based on the attacker-controlled length value without verifying the actual stream length. This provided another avenue for uncontrolled memory allocation.
Additionally, PR #7069 addressed a resource leak in the background export workers (BatchExportTaskWorker and PeriodicExportingMetricReaderTaskWorker). In specific environments, such as Blazor WebAssembly, these workers leaked asynchronous tasks. This failure to release task resources resulted in linear memory growth over the lifetime of the application.
These combined findings indicate a systemic pattern of trust in external input lengths and suboptimal resource management in earlier versions of the SDK. The transition to Span-based processing and strict boundary validation in version 1.15.3 marks a critical architectural hardening against resource exhaustion attacks.
The primary remediation for CVE-2026-40894 is to update all dependencies on OpenTelemetry.Api and OpenTelemetry.Extensions.Propagators to version 1.15.3 or later. Developers must ensure that all transient dependencies are also updated, which may require explicit package references in the project file to force NuGet to resolve the patched version.
If immediate patching is not possible, organizations can apply mitigation controls at the ingress layer. Web Application Firewalls (WAF) or API Gateways can be configured to drop requests containing baggage, b3, or uber-trace-id headers that exceed a specific character length or contain an excessive number of delimiter characters. Limiting the length of these headers to 1,024 characters will effectively mitigate the denial-of-service vector without interrupting normal distributed tracing operations.
Organizations should monitor application memory metrics and garbage collection frequency. Sudden spikes in Gen 2 collections, coupled with high allocations of string arrays, indicate potential exploitation attempts. Analyzing incoming HTTP traffic for abnormally large or malformed tracing headers will confirm the presence of this attack vector.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenTelemetry.Api OpenTelemetry | >= 0.5.0-beta.2, <= 1.15.2 | 1.15.3 |
OpenTelemetry.Extensions.Propagators OpenTelemetry | >= 1.3.1, <= 1.15.2 | 1.15.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-789 |
| Attack Vector | Network |
| CVSS v3.1 | 5.3 |
| EPSS | N/A |
| Impact | Denial of Service (DoS) |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
Memory Allocation with Excessive Size Value