CVE-2026-32873 Overview
CVE-2026-32873 is a Denial of Service vulnerability affecting ewe, a Gleam web server. The vulnerability exists in the handle_trailers function where rejected trailer headers (forbidden or undeclared) cause an infinite loop. When handle_trailers encounters such a trailer, three code paths (lines 520, 523, 526) recurse with the original buffer (rest) instead of advancing past the rejected header (Buffer(header_rest, 0)), causing decoder.decode_packet to re-parse the same header on every iteration.
The resulting loop has no timeout or escape mechanism, causing the BEAM process to permanently wedge at 100% CPU utilization. Any application that calls ewe.read_body on chunked requests is affected, and this is exploitable by any unauthenticated remote client before control returns to application code, making an application-level workaround impossible.
Critical Impact
Unauthenticated remote attackers can permanently wedge BEAM processes at 100% CPU through malformed chunked transfer requests, causing complete service denial with no application-level mitigation possible.
Affected Products
- ewe Gleam web server versions 0.8.0 through 3.0.4
- Applications using ewe.read_body on chunked requests
- Any deployment accepting untrusted HTTP requests with chunked transfer encoding
Discovery Timeline
- 2026-03-20 - CVE-2026-32873 published to NVD
- 2026-03-20 - Last updated in NVD database
Technical Details for CVE-2026-32873
Vulnerability Analysis
The vulnerability is classified under CWE-825 (Expired Pointer Dereference), though the core issue manifests as an infinite recursion problem in the trailer header handling logic. The flaw allows network-accessible exploitation without any authentication requirements or user interaction.
The handle_trailers function processes HTTP trailer headers in chunked transfer-encoded requests. When the function encounters a rejected trailer (either forbidden by HTTP specification or undeclared in the Trailer header field), it should advance the buffer past the rejected header and continue processing. Instead, three separate code paths at lines 520, 523, and 526 incorrectly recurse using the original buffer (rest) rather than the properly advanced buffer position (Buffer(header_rest, 0)).
This causes decoder.decode_packet to continuously re-parse the same header data indefinitely. Since there is no timeout, iteration limit, or escape condition, the BEAM virtual machine process becomes permanently stuck in this recursive loop, consuming 100% CPU resources.
Root Cause
The root cause is improper buffer advancement in the recursive trailer handling logic. When a trailer header is rejected (forbidden or undeclared), the function should consume the header bytes from the buffer before recursing. The bug occurs because three code paths pass the original rest buffer to the recursive call instead of Buffer(header_rest, 0), which would properly skip past the processed header. This creates an infinite loop condition where the same rejected header is parsed repeatedly without any progress through the input buffer.
Attack Vector
An unauthenticated remote attacker can exploit this vulnerability by sending a specially crafted HTTP request with chunked transfer encoding containing a forbidden or undeclared trailer header. Since the vulnerability triggers in ewe.read_body before control returns to application code, there is no opportunity for application-level filtering or mitigation.
The attack requires only network access to a vulnerable ewe server. A single malicious request can permanently consume 100% CPU on the target BEAM process. Multiple such requests can exhaust all available system resources, causing complete denial of service for the affected application and potentially the entire server.
The following patch shows the fix implemented in version 3.0.5, which properly manages buffer state:
let information = information.worker(builder.information_name)
let glisten_supervisor =
- glisten.new(
- fn(conn) { #(http_.transform_connection(conn), None) },
- handler_.loop(handler, on_crash),
- )
+ glisten.new(fn(_conn) { #(Nil, None) }, handler_.loop(handler, on_crash))
|> glisten.bind(builder.interface)
|> fn(glisten_builder) {
case builder.ipv6 {
Source: GitHub Commit
The fix also introduces a new Buffer module to properly track buffer state:
+import gleam/bit_array
+import gleam/int
+
+pub type Buffer {
+ Buffer(data: BitArray, remaining: Int)
+}
+
+pub fn new(initial: BitArray) -> Buffer {
+ Buffer(initial, 0)
+}
+
+pub fn sized(buffer: Buffer, size: Int) -> Buffer {
+ Buffer(buffer.data, size)
+}
+
+pub fn empty() -> Buffer {
+ Buffer(<<>>, 0)
+}
+
+pub fn append(buffer: Buffer, data: BitArray) -> Buffer {
+ let remaining = int.max(0, buffer.remaining - bit_array.byte_size(data))
+ Buffer(<<buffer.data:bits, data:bits>>, remaining)
+}
+
+pub fn append_size(buffer: Buffer, data: BitArray, size: Int) -> Buffer {
+ let remaining = int.max(0, buffer.remaining - size)
+ Buffer(<<buffer.data:bits, data:bits>>, remaining)
+}
Source: GitHub Commit
Detection Methods for CVE-2026-32873
Indicators of Compromise
- BEAM processes exhibiting sustained 100% CPU utilization without corresponding legitimate workload
- HTTP requests with chunked transfer encoding containing forbidden or undeclared trailer headers
- Application unresponsiveness following receipt of chunked HTTP requests
- Server logs showing incomplete request processing for chunked transfers
Detection Strategies
- Monitor BEAM process CPU utilization for sustained spikes to 100% that do not resolve naturally
- Implement network-level inspection for HTTP requests with chunked transfer encoding and suspicious trailer headers
- Deploy application performance monitoring to detect request processing timeouts and hangs
- Use BEAM observer or similar tools to identify stuck processes in the handle_trailers function call stack
Monitoring Recommendations
- Configure alerting thresholds for BEAM process CPU utilization exceeding normal baselines for extended periods
- Implement request timeout monitoring at the load balancer or reverse proxy level
- Enable detailed HTTP access logging to capture trailer header contents for forensic analysis
- Set up synthetic monitoring to detect application availability degradation
How to Mitigate CVE-2026-32873
Immediate Actions Required
- Upgrade ewe to version 3.0.5 or later immediately
- Audit all applications using ewe versions 0.8.0 through 3.0.4 for exposure
- Consider temporarily disabling chunked transfer encoding at the reverse proxy layer if upgrade is not immediately possible
- Implement rate limiting on incoming HTTP requests to reduce attack surface
Patch Information
The vulnerability is fixed in ewe version 3.0.5. The fix properly advances the buffer past rejected trailer headers before recursing, preventing the infinite loop condition. The patch introduces a new Buffer module (src/ewe/internal/buffer.gleam) that correctly tracks buffer state and remaining bytes.
Update your dependencies to ewe version 3.0.5 or later. For Gleam projects using the Hex package manager, update your gleam.toml accordingly. Review the GitHub Security Advisory for complete details on the fix.
Workarounds
- Deploy a reverse proxy (nginx, HAProxy) in front of ewe to filter or reject requests with chunked transfer encoding until patching is complete
- Implement network-level filtering to block requests containing trailer headers from untrusted sources
- Use a web application firewall (WAF) configured to inspect and sanitize chunked transfer-encoded requests
- Consider running multiple ewe instances behind a load balancer to provide resilience against single-process denial of service
# Example nginx configuration to reject chunked requests (temporary workaround)
# Add to your nginx server block
if ($http_transfer_encoding ~* "chunked") {
return 413;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

