Apr 23, 2026·6 min read·33 visits
A memory allocation vulnerability in the OpenTelemetry .NET SDK allows a malicious gRPC endpoint to crash the client application via a crafted grpc-status-details-bin trailer.
The OpenTelemetry .NET SDK is vulnerable to a Denial of Service (DoS) flaw due to unbounded memory allocation during the deserialization of gRPC status details. An attacker controlling the telemetry endpoint or performing a Man-in-the-Middle attack can crash the instrumented application by supplying a crafted Protobuf payload.
The OpenTelemetry .NET SDK provides a framework for generating and exporting telemetry data. The OpenTelemetry.Exporter.OpenTelemetryProtocol package handles the transmission of this data to an OpenTelemetry Protocol (OTLP) collector via gRPC. This component is widely integrated into .NET enterprise applications to monitor performance and trace distributed requests.
During telemetry export, the gRPC client processes response metadata from the collector. If the collector returns a retryable status code, such as ResourceExhausted or Unavailable, the client intercepts the grpc-status-details-bin trailer. This trailer contains a serialized Protobuf payload specifying retry delay information.
The parser handling this trailer exhibits a CWE-789 vulnerability, classified as Memory Allocation with Excessive Size Value. The manual Protobuf deserialization routine fails to validate the declared length of length-delimited fields against the actual byte stream size. An attacker can supply a malicious trailer to force arbitrary heap allocations, resulting in an unhandled memory exception that terminates the application process.
The root cause of this vulnerability lies in the manual Protobuf parsing logic implemented within the GrpcStatusDeserializer class. Specifically, the flaw exists in methods handling length-delimited fields, such as DecodeBytes, DecodeDuration, and DecodeAny. Protobuf encodes length-delimited data using a variable-length integer (varint) to specify the subsequent payload size.
Upon encountering a length-delimited field, the vulnerable deserializer reads the varint from the network stream using the DecodeVarint method. The returned 64-bit integer is cast to a 32-bit integer and directly utilized as the size parameter for a new byte array allocation. The operation executes new byte[length] unconditionally.
The deserializer omits critical bounds checking prior to this allocation step. It does not evaluate whether the requested array length exceeds the remaining bytes available in the underlying stream. Consequently, a small network payload containing an artificially inflated varint instructs the .NET runtime to allocate an array far larger than the actual data transfer.
Prior to version 1.15.2, the DecodeBytes method allocated memory blindly based on the parsed varint. The underlying flaw manifests directly in the array instantiation logic. The runtime trusts the externally supplied length value entirely.
// Vulnerable Implementation (prior to 1.15.2)
private static byte[] DecodeBytes(Stream stream)
{
var length = (int)DecodeVarint(stream);
// Unbounded allocation based on untrusted input
var buffer = new byte[length];
int read = stream.Read(buffer, 0, length);
return buffer;
}The remediation introduced in PR #7064 adds a dedicated CheckLength validation method. This function intercepts the parsing flow immediately after the varint decoding phase. It imposes strict constraints on the requested allocation size.
// Patched Implementation (1.15.2)
private static byte[] DecodeBytes(Stream stream)
{
var length = (int)DecodeVarint(stream);
CheckLength(length, stream);
var buffer = new byte[length];
int read = stream.Read(buffer, 0, length);
return buffer;
}
private static void CheckLength(long length, Stream stream)
{
if (length < 0 || length > int.MaxValue)
{
throw new InvalidDataException($"Invalid length: {length}.");
}
long available = stream.Length - stream.Position;
if (length > available)
{
throw new EndOfStreamException();
}
}The CheckLength method introduces dual validation requirements. First, a sanity check ensures the value is non-negative and within the limits of a standard .NET array index. Second, a bounds check verifies that the requested memory capacity does not exceed the remaining readable bytes in the stream buffer.
Exploitation requires the attacker to control the network traffic flowing from the instrumented client to the telemetry collector. The attacker must act as a malicious OTLP endpoint or successfully execute a Man-in-the-Middle attack. The attack surface relies on the target client attempting an export operation and subsequently parsing the provided gRPC response.
The attacker crafts an HTTP/2 response utilizing a gRPC retryable status code, such as RESOURCE_EXHAUSTED. This response is configured to include the grpc-status-details-bin trailer. The trailer payload is engineered as a minimal Protobuf structure where the length varint declares a required size near the 2GB limit (e.g., 0x7FFFFFF0), but the physical payload size is negligible.
When the client processes the trailer, the DecodeBytes function invokes the memory allocation routine. The .NET Common Language Runtime (CLR) attempts to secure a contiguous memory block on the Large Object Heap corresponding to the malicious varint. This immediate allocation request exhausts the available application memory, triggering a fatal System.OutOfMemoryException.
The exploitation of CVE-2026-40891 results in an absolute Denial of Service condition for the application hosting the OpenTelemetry .NET SDK. The unhandled memory exception bypasses standard application error handling mechanisms, leading to instantaneous process termination. This failure disrupts the primary business functions of the instrumented software.
The assigned CVSS vector (CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H) accurately reflects the attack constraints. The High Attack Complexity (AC:H) and Adjacent Network (AV:A) metrics acknowledge the necessity of intercepting or terminating the specific gRPC connection. The attacker requires precise network positioning to inject the malicious trailer.
In containerized and orchestrated environments, such as Kubernetes clusters, this vulnerability introduces secondary operational risks. A process crashing continuously upon initialization or during its first telemetry export cycle causes orchestration controllers to enter crash-loop backoff states. This behavior induces unnecessary resource thrashing and prolongs service outages.
The authoritative resolution for CVE-2026-40891 requires updating the target application dependencies. Security teams must ensure that the OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet package is upgraded to version 1.15.2 or later. This version implements the necessary bounds-checking logic within the Protobuf deserialization pipeline.
Organizations should enforce strict Transport Layer Security (TLS) configuration across all gRPC export channels. Mandating encrypted, mutually authenticated connections mitigates the risk of Man-in-the-Middle attacks. This defensive measure restricts the exploitability of the vulnerability strictly to compromised or explicitly malicious OTLP collectors.
As a defense-in-depth strategy, administrators should harden the gRPC client configurations. Setting aggressive limits on the MaxResponseHeadersSize property ensures the client rejects abnormally large metadata payloads prior to invoking the deserialization logic. This configuration limits the attack surface available for complex payload injection.
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenTelemetry.Exporter.OpenTelemetryProtocol OpenTelemetry | 1.13.1 - < 1.15.2 | 1.15.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-789 |
| Attack Vector | Adjacent Network |
| CVSS v3.1 Score | 5.3 |
| Exploit Status | Proof of Concept |
| Impact | Denial of Service (DoS) |
| KEV Status | Not Listed |
The product allocates memory based on an untrusted size value, but it does not sufficiently validate the size, allowing the allocation of a large amount of memory leading to a denial of service.
Gitea versions from 1.5.0 before 1.26.3 contain a security vulnerability in their multi-factor authentication (MFA) logic. This vulnerability allows valid TOTP codes to be accepted multiple times across web authentication flows and the Basic Auth X-Gitea-OTP header path. Due to a TOCTOU race condition and a lack of state tracking in programmatic auth pathways, attackers with valid credentials can replay single-use OTP codes.
A critical validation bypass exists in FasterXML jackson-core due to an incomplete fix for GHSA-72hv-8253-57qq. When parsing JSON asynchronously using NonBlockingUtf8JsonParserBase, the StreamReadConstraints.maxNumberLength constraint is bypassed when numeric inputs are received in small, non-terminating chunks. The parser continually accumulates digit-only input in an internal buffer without triggering validation constraints, resulting in potential heap memory exhaustion and application-level Denial of Service.
A critical second-order code injection vulnerability exists in the migration generation engine of TypeORM. When TypeORM introspects a database schema to automatically generate migration files, it writes schema metadata directly into JavaScript/TypeScript migration files inside ES2015 template literals. Because the generator failed to sanitize template literal string interpolation markers and backslashes, attackers with control over database metadata can execute arbitrary code on the developer environment or within a CI/CD pipeline.
A security logic flaw in Loofah, a Ruby HTML/XML sanitization library, allowed unauthenticated attackers to bypass local-reference restrictions on SVG elements. Prior to version 2.25.2, Loofah only sanitized the legacy namespaced "xlink:href" attribute when enforcing local URI fragments on SVG elements like "<use>". It did not validate or sanitize the plain, non-namespaced "href" attribute introduced in the SVG 2 standard. This structural omission allowed attackers to construct SVG elements referencing external domains, paving the way for arbitrary resource loading and cross-site scripting (XSS).
A critical HTML sanitization bypass vulnerability in the Ruby library Loofah allows unauthenticated remote attackers to execute Stored Cross-Site Scripting (XSS) attacks. By using semicolon-less numeric character references (NCRs) to encode protocol characters, attackers can evade backend URI verification filters while ensuring the malicious protocol is successfully decoded and executed by client-side web browsers.
GHSA-HRXH-6V49-42GF is a critical security advisory addressing two distinct vulnerabilities within gRPC-Go: an HTTP/2 Control Buffer Flooding weakness that allows unauthenticated denial of service, and xDS Role-Based Access Control parser weaknesses that lead to authorization bypasses and application panics.