Mar 20, 2026·5 min read·5 visits
A CWE-789 vulnerability in Elastic Metricbeat's Prometheus remote_write module allows network attackers to crash the service. Sending a crafted Snappy payload with a spoofed decompressed size forces the process to allocate excessive memory, triggering the OOM killer.
Elastic Metricbeat is vulnerable to an unauthenticated Denial of Service (DoS) attack via a memory exhaustion flaw in the Prometheus remote_write HTTP handler. The vulnerability stems from insufficient validation of declared uncompressed sizes within Snappy-compressed payloads, allowing an attacker to trigger an Out-of-Memory (OOM) process termination.
Elastic Metricbeat exposes a Prometheus remote_write module to ingest metrics via HTTP POST requests. This module relies on Snappy compression to handle incoming protocol buffers, conforming to the Prometheus remote write specification. CVE-2026-26931 is a memory exhaustion vulnerability (CWE-789) located within this HTTP handler.
The vulnerability occurs because the remote_write endpoint processes Snappy-compressed payloads without validating the declared decompressed size. An attacker with network access to the Metricbeat instance can send a crafted payload that triggers an Out-of-Memory (OOM) condition upon processing.
This allocation failure results in the termination of the Metricbeat process by the operating system kernel. The Prometheus remote_write module is not enabled by default, restricting the attack surface strictly to environments where administrators have explicitly activated this specific metricset.
The root cause is an excessive memory allocation defect triggered during the decompression phase of the Prometheus remote write protocol. The Go implementation of the Snappy library (golang/snappy) reads a varint-encoded header from the compressed stream to determine the size of the uncompressed data. The library utilizes this header to allocate the destination buffer via the snappy.Decode() function.
In vulnerable versions of Metricbeat, the application passes the raw HTTP request body directly to snappy.Decode() without prior validation of the varint header. A malicious payload can declare an artificially large decompressed size, such as MaxInt64, while containing only a few bytes of actual payload data.
Upon processing this manipulated payload, the Go runtime attempts to allocate the requested memory block immediately. This allocation request exceeds the available physical memory and swap space on the host system. Consequently, the Linux OOM killer responds by terminating the Metricbeat process to preserve system stability.
The flaw exists in the HTTP handler logic for the remote_write endpoint. Prior to the fix, the code read the compressed body and directly invoked the decompression routine. This created an unmediated path from an attacker-controlled HTTP request to a bounded memory allocator.
// Vulnerable Implementation Pattern
compressed, err := io.ReadAll(req.Body)
if err != nil {
return err
}
// Unsafe allocation based on attacker-controlled header
uncompressed, err := snappy.Decode(nil, compressed)The patch introduced in commit de072c4e371eafeb2a42d65b9ad513f666e4ffd7 implements two distinct validation layers. First, it restricts the maximum size of the raw HTTP request body using http.MaxBytesReader, preventing attackers from sending excessively large compressed payloads over the network.
Second, the patch inspects the Snappy header before initiating the full decode process. The code now extracts the declared length using snappy.DecodedLen() and validates it against a configurable threshold named max_decoded_body_bytes.
// Patched Implementation Pattern
decodedLen, err := snappy.DecodedLen(compressed)
if err != nil {
return err
}
if int64(decodedLen) > config.MaxDecodedBodyBytes {
http.Error(w, "Request Entity Too Large", http.StatusRequestEntityTooLarge)
return nil
}This pre-validation ensures the runtime only allocates memory for payloads that conform to expected operational limits. The fix comprehensively addresses the root cause for this specific code path by enforcing strict boundaries on memory operations.
Exploitation requires adjacent network access (AV:A) to the Metricbeat HTTP endpoint, which defaults to port 9201. The attacker does not require authentication, provided they can route traffic to the affected service port. The attack requires minimal privileges and interactions, categorizing it as low complexity.
The attack sequence begins with the generation of a malicious Snappy payload. The attacker constructs a valid Snappy stream where the initial varint header specifies a decompression size exceeding the target system's available RAM. The actual compressed data block remains extremely small, ensuring minimal network overhead during transmission.
The attacker embeds this payload into an HTTP POST request formatted for the Prometheus remote_write protocol and transmits it to the vulnerable Metricbeat instance. Upon receiving the request, the application parses the header and requests the excessively large allocation from the Go memory allocator, resulting in immediate process termination.
The primary remediation strategy requires upgrading the Elastic Metricbeat deployment to the patched releases. Users operating on the 8.x branch must upgrade to version 8.19.13. Users operating on the 9.x branch must upgrade to version 9.2.5.
The updated versions introduce necessary configuration parameters to control resource consumption: max_compressed_body_bytes (defaulting to 2MB) and max_decoded_body_bytes (defaulting to 10MB). Administrators must evaluate these defaults and adjust them if legitimate metric payloads in their environment exceed these limits.
For environments where immediate patching is unfeasible, administrators should disable the remote_write metricset within metricbeat.yml. Removing or commenting out this module disables the vulnerable HTTP listener entirely, eliminating the attack surface.
If the module must remain operational, administrators should implement strict network access controls. Restricting access to port 9201 via firewall rules or security groups ensures only authorized Prometheus instances can communicate with the endpoint, preventing untrusted network segments from delivering the exploit.
CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Metricbeat Elastic | 8.0.0 <= v <= 8.19.12 | 8.19.13 |
Metricbeat Elastic | 9.0.0 <= v <= 9.2.4 | 9.2.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-789 |
| Attack Vector | Adjacent Network (AV:A) |
| CVSS Score | 5.7 (Medium) |
| Impact | Denial of Service (OOM Process Crash) |
| Exploit Status | Unexploited |
| CISA KEV | Not Listed |
Memory Allocation with Excessive Size Value