Sep 29, 2026·7 min read·9 visits
A high-severity CPU exhaustion vulnerability in OpenTelemetry-Go's logging SDK allows remote attackers to cause a denial of service via tight-loop execution when downstream exporters experience backpressure.
An uncontrolled resource consumption vulnerability in the logs SDK of OpenTelemetry-Go allows remote attackers to trigger a denial of service. Under conditions of downstream exporter backpressure, the BatchingProcessor enters a tight loop, exhausting CPU resources. This occurs because the processor immediately schedules retry attempts without waiting for its ticker interval, spinning continuously when the internal queue remains filled above the batch size. The issue affects all versions prior to v0.21.0 of the go.opentelemetry.io/otel/sdk/log package.
The OpenTelemetry-Go logging SDK provides the fundamental instrumentation framework for collecting, processing, and exporting log records in Go applications. The BatchingProcessor component within go.opentelemetry.io/otel/sdk/log asynchronously batches log records to decouple the primary application execution path from network latency and log serialization overhead. This separation ensures that high-throughput logging operations do not block critical runtime requests.
To manage this asynchronous pipeline, the BatchingProcessor coordinates incoming records using an internal ring buffer queue and delegates the transmission of batch payloads to an underlying exporter. However, in versions prior to v0.21.0, the system architecture introduces a fatal feedback loop when the exporter is unable to process logs. This scenario typically arises when the downstream OpenTelemetry Collector or the central logging endpoint experiences latency spikes, resource exhaustion, or network disconnection.
Under these conditions, a design flaw in the batching processor's execution loop triggers a busy-spin cycle. Instead of enforcing backpressure or sleeping during exporter unreadiness, the processing routine continuously schedules execution iterations. The vulnerability is classified under CWE-400 (Uncontrolled Resource Consumption) and CWE-834 (Excessive Iteration), manifesting as system-wide CPU exhaustion that starves surrounding application logic of computational cycles.
The root cause of this vulnerability lies in the control flow of the polling goroutine located in the BatchingProcessor.poll function within batch.go. The processor splits its workload between a polling goroutine, which monitors the buffer queue and drives batch creation, and an export goroutine managed by bufferExporter, which maintains a single-slot asynchronous export-request buffer.
The polling goroutine runs a continuous execution loop governed by a ticker and a trigger channel named pollTrigger. On each iteration, the loop evaluates the readiness of the exporter using b.exporter.Ready(). If the exporter is ready, the processor dequeues up to b.batchSize elements from the queue and enqueues them for export. If the exporter is unready due to downstream backpressure, the else branch is executed instead:
} else {
qLen = b.q.Len()
}Following this branch, the loop checks if the length of the queue (qLen) remains greater than or equal to the configured batchSize. If this condition is met, the processor attempts to trigger an immediate export cycle to process the pending batch:
if qLen >= b.batchSize {
select {
case b.pollTrigger <- struct{}{}:
default:
}
}When the exporter is backpressured, Ready() repeatedly evaluates to false. However, because log records continue to accumulate in the queue from application activities, qLen remains higher than b.batchSize. The processor immediately dispatches a token onto the buffered b.pollTrigger channel. In the subsequent iteration of the select block, the runtime selects the pollTrigger channel immediately, resetting the ticker but bypassing any sleep interval. The loop executes again, finds the exporter unready, evaluates the queue length as high, sends another trigger, and repeats this sequence infinitely, resulting in 100% CPU utilization on the executing core.
An analysis of the patch implemented in OpenTelemetry-Go PR #8620 shows a comprehensive structural redesign of the batch processing workflow. The vulnerable dual-goroutine coordination mechanism has been completely replaced with a single, synchronous, event-driven worker goroutine.
In the patched version, the complex poll method has been eliminated. The redesigned process function manages incoming events synchronously using a unified select statement. The critical structural difference lies in the removal of the self-scheduling feedback loop and the introduction of block-level safety parameters:
// Patched implementation in batch.go
func (b *BatchProcessor) process(interval time.Duration) {
go func() {
timer := time.NewTimer(interval)
defer timer.Stop()
buf := make([]Record, b.batchSize)
for {
select {
case req := <-b.shutdown:
err := b.shutdownExporter(req.ctx)
close(b.done)
req.respond(err)
return
case req := <-b.flush:
err := b.flushExporter(req.ctx)
req.respond(err)
case <-timer.C:
resetTimer(timer, interval)
b.exportBatch(buf)
case <-b.exportTrigger:
resetTimer(timer, interval)
b.exportBatch(buf)
}
}
}()
}By routing all execution paths through the single event loop, the processor ensures that the exporter must complete or timeout before the next event can be evaluated. If the exporter blocks due to downstream latency, the synchronous execution of b.exportBatch(buf) blocks the worker goroutine, using zero CPU cycles. When the bounded queue b.q fills up entirely, the thread-safe ring buffer naturally discards excess records according to its drop policy, ensuring memory stability without generating infinite loops.
Exploitation of CVE-2026-81872 does not require a highly specialized payload or authentication bypasses. An attacker must manipulate the environment to trigger two conditions simultaneously: downstream backpressure on the exporter and log generation within the application.
To induce exporter backpressure, an attacker can launch network-level disruptions targeting the OpenTelemetry Collector endpoint or the backend storage system. Techniques such as TCP SYN flooding or connection pool starvation against the collector's ingress ports will delay or drop outgoing export payloads. Alternatively, if the collector endpoint is exposed or shares infrastructure, sending complex payloads directly to the database backend can cause latency cascades, prompting the SDK's exporter to transition to an unready state.
While the exporter is blocked, the attacker drives log volume within the target application. This is achieved by sending requests that trigger logging actions, such as input validation errors, unauthenticated login failures, or parsing exceptions. Because these requests trigger logging threads, the SDK's internal queue b.q fills past the batchSize limit. The internal pollTrigger then fires, locking up the CPU core. If the host environment utilizes multi-core systems, sending multiple concurrent streams of logging traffic can lock up multiple execution threads, leading to complete service degradation.
The primary impact of CVE-2026-81872 is severe denial of service. Because the tight loop runs within the user space of the Go runtime, it bypasses standard operating system scheduling controls that manage separate application processes. The Go scheduler multiplexes goroutines across available operating system threads (GOMAXPROCS), meaning a spinning goroutine will occupy an entire logical processor core continuously.
In containerized environments such as Kubernetes or Docker, this behavior results in rapid CPU exhaustion. If CPU limits are strictly enforced, the container will face heavy throttling, making it unable to handle incoming requests and prompting readiness probe failures that lead to container restarts. If CPU limits are not configured, a single vulnerable container can exhaust host-level resources, affecting adjacent workloads on the same physical node.
This vulnerability has been assigned a CVSS v4.0 Base Score of 6.3 with the vector CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N. While classified as low impact on availability under standard CVSS criteria, the logical consequence in production systems is complete service unavailability, as the underlying Go runtime loses the ability to execute other concurrent goroutines efficiently.
Remediation requires upgrading the go.opentelemetry.io/otel/sdk/log package to version v0.21.0 or higher. This release removes the vulnerable polling architecture and implements the single-threaded event loop design.
To identify vulnerable deployments, security teams should execute static dependency scanning against compiled binaries and Go module files. The following command can be used within Go project workspaces to determine the current module version:
go list -m all | grep "go.opentelemetry.io/otel/sdk/log"If upgrading immediately is not feasible, organizations can implement operational workarounds to reduce exposure. The export timeout parameter, configured via the OTEL_BLRP_EXPORT_TIMEOUT environment variable, should be decreased from its default of 30 seconds to a lower value such as 5 seconds. This forces the exporter to fail quickly when encountering downstream latency, preventing the queue from remaining in a prolonged state of blocked readiness and reducing the window of CPU exhaustion.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
go.opentelemetry.io/otel/sdk/log OpenTelemetry | < v0.21.0 | v0.21.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 (Uncontrolled Resource Consumption), CWE-834 (Excessive Iteration) |
| Attack Vector | Network (AV:N) |
| CVSS Score | 6.3 (Medium) |
| EPSS Score | 0.00524 (Percentile: 42.16%) |
| Impact | Denial of Service / CPU Exhaustion |
| Exploit Status | No weaponized exploits exist in the wild |
| KEV Status | Not listed in CISA KEV |
The software does not properly control the allocation and maintenance of limited resources, enabling an actor to consume excessive CPU resources via an infinite loop.
A DOM-based Cross-Site Scripting (XSS) vulnerability exists in the Laravel exception debug page rendering pipeline when APP_DEBUG=true is active. This flaw allows an attacker to execute arbitrary client-side JavaScript in the security context of an authenticated user's session when they hover over interactive code-trace tooltips handled by Tippy.js.
A critical denial-of-service vulnerability in the adm-zip npm package allows attackers to bypass decompression-bomb protections introduced in version 0.5.18. By declaring the uncompressed file size as exactly 0, an attacker can disable the maxOutputLength constraint in the Node.js zlib wrapper, leading to complete system memory exhaustion and process crashes.
CVE-2026-76844 is a high-severity path traversal vulnerability in webpack-dev-middleware affecting multiple version branches. It stems from an incomplete fix for CVE-2024-29180 when serving files via a physical filesystem with a non-slash-terminated publicPath configuration. Attackers can bypass directory validation to access files situated one level above the intended output directory.
A Server-Side Request Forgery (SSRF) vulnerability exists in FasterXML jackson-databind before versions 2.18.9, 2.21.5, 2.22.1, 3.1.5, and 3.2.1. The flaw occurs during the deserialization of java.net.InetAddress fields, where the library implicitly triggers eager DNS lookups. Unauthenticated remote attackers can exploit this behavior by passing arbitrary hostnames in JSON fields, forcing target servers to make outbound DNS lookup requests.
An insecure deserialization vulnerability exists in FasterXML jackson-databind due to improper validation of URI schemes when resolving java.nio.file.Path properties. When binding untrusted JSON input to a Path field, the deserializer resolves attacker-supplied URIs without restriction. If the scheme is unrecognized by the default filesystem, the application falls back to querying registered SPI FileSystemProvider instances, causing class loading and potential side effects in environments with custom providers.
CVE-2026-68497 is a high-severity CPU Denial of Service (DoS) vulnerability in jackson-databind. It arises because the library bypasses default input constraint checks when parsing stringified XML datatypes, subsequently passing arbitrary-length inputs to JDK constructors with quadratic execution complexity.