Mar 17, 2026·8 min read·4 visits
Infinite loop in ewe's HTTP trailer parser allows unauthenticated remote attackers to cause a complete Denial of Service (DoS) via crafted chunked requests.
The ewe web server, developed in Gleam for the Erlang BEAM ecosystem, contains a Denial of Service vulnerability stemming from an infinite loop in its HTTP trailer parsing logic. Versions prior to 3.0.3 fail to properly advance the network buffer when encountering invalid or forbidden chunked trailers. This flaw allows an unauthenticated remote attacker to trigger 100% CPU exhaustion by sending a maliciously crafted HTTP/1.1 request.
The ewe package, a web server built for the Erlang BEAM ecosystem using the Gleam language, is vulnerable to a Denial of Service (DoS) flaw tracked as GHSA-4W98-XF39-23GP. The vulnerability occurs within the HTTP trailer parsing logic handling chunked transfer encoding. Specifically, a logic error in buffer management leads to a loop with an unreachable exit condition (CWE-835). This allows an unauthenticated remote attacker to exhaust server resources without any specific configuration requirements.
HTTP/1.1 chunked transfer encoding allows senders to append "trailers" to a message after the final zero-length body chunk. These trailers are structurally identical to standard HTTP headers and provide metadata that could not be calculated before the body stream began. The ewe server implements a dedicated function, handle_trailers, to parse these trailing headers sequentially from the incoming TCP byte stream.
The vulnerability manifests when the server encounters a properly formatted trailer that fails subsequent application-level validation. Instead of discarding the invalid trailer and advancing the buffer pointer, the server recursively calls the parsing function using the original buffer state. This creates an infinite recursive loop that permanently locks the processing thread.
The security impact is strictly limited to availability. The vulnerability does not expose memory contents, nor does it allow for arbitrary code execution. However, because the Erlang VM (BEAM) allocates scheduler threads to handle incoming connections, triggering this loop on multiple connections can exhaust the scheduler pool and render the server completely unresponsive to legitimate HTTP traffic.
The root cause resides in the src/ewe/internal/http1.gleam file, specifically within the handle_trailers function. This function reads recursively from the network buffer, extracting one header field at a time until the sequence terminates with a final \r\n. A successful byte extraction yields a header name, a header value, and the remaining unparsed buffer, internally tracked as header_rest.
Upon extracting a header, the function performs three distinct validation checks. First, it verifies that the extracted header name is not on the list of forbidden trailers, such as Host or Transfer-Encoding. Second, it checks if the trailer was explicitly declared in the initial request headers via the Trailer field. Finally, it attempts to decode the raw byte value into a valid UTF-8 string.
If any of these three validation steps fail, the parser must discard the current trailer and continue processing the rest of the stream. In vulnerable versions of ewe (prior to 3.0.3), the error-handling branches for these validation failures invoke handle_trailers recursively using the rest variable instead of header_rest. The rest variable represents the buffer state before the current trailer was extracted.
Passing rest back into handle_trailers guarantees that the next iteration will parse the exact same invalid trailer. The parser extracts the same header, fails the same validation check, and recurses again with the identical buffer. This creates a tight, infinite recursive loop that never consumes additional bytes from the network socket and never yields a return value.
The remediation of this vulnerability required structural changes to how ewe manages network buffers, implemented across two distinct commits. The initial commit, 8513de9dcdd0005f727c0f6f15dd89f8d626f560, introduced a dedicated Buffer type in src/ewe/internal/buffer.gleam. This abstraction tracks the raw byte array and the current parsing offset, establishing the foundation for precise state management during recursive parsing.
The primary fix was implemented in commit d8b9b8a86470c0cb5696647997c2f34763506e37 within src/ewe/internal/http1.gleam. The diff demonstrates the replacement of the vulnerable rest variable with a newly constructed Buffer object pointing to the advanced state. In the vulnerable implementation, specific error paths explicitly routed failures back to the unadvanced state.
// VULNERABLE CODE PATHS (Pre-3.0.3)
case bit_array.to_string(value) {
Ok(value) -> { /* Valid branch */ }
Error(Nil) -> handle_trailers(req, set, rest) // Flaw: Reuses original offset
}
False -> handle_trailers(req, set, rest) // Flaw: Reuses original offset
Error(Nil) -> handle_trailers(req, set, rest) // Flaw: Reuses original offsetIn the patched version, the error branches utilize the header_rest variable, which represents the remaining byte array after the discarded trailer. By wrapping header_rest in the new Buffer abstraction, the parser explicitly discards the invalid header bytes and moves processing forward to the next sequence.
// PATCHED CODE PATHS (3.0.3+)
case bit_array.to_string(value) {
Ok(value) -> { /* Valid branch */ }
Error(Nil) -> handle_trailers(req, set, Buffer(header_rest, 0))
}
False -> handle_trailers(req, set, Buffer(header_rest, 0))
Error(Nil) -> handle_trailers(req, set, Buffer(header_rest, 0))This patch comprehensively addresses the infinite loop logic flaw. By enforcing forward progress through the byte stream on every parsing iteration, the loop is mathematically guaranteed to terminate when the buffer is eventually exhausted, regardless of the input data's structural validity.
Exploiting this vulnerability requires zero authentication and relies entirely on standard HTTP networking mechanics. An attacker merely needs the ability to establish a TCP connection to the exposed ewe web server port. The exploit payload is delivered entirely within a single HTTP/1.1 request, utilizing chunked transfer encoding to bypass initial header parsing constraints.
The attacker initiates the exploit by sending standard HTTP headers, importantly including Transfer-Encoding: chunked. The body of the request must conform to chunked encoding rules, terminating with a zero-length chunk (0\r\n). Immediately following the zero-length chunk, the attacker appends the malicious trailer payload.
The payload itself is trivially simple: any properly formatted HTTP header that triggers one of the validation failures will suffice. Sending a forbidden header such as Host: attacker.com\r\n\r\n ensures the parser successfully reads the structure but rejects the key name. Because the key is rejected, the vulnerable logic path is triggered, permanently trapping the connection process in the infinite loop.
When the server receives the malicious trailer, the Erlang process handling the connection enters the infinite recursive state. The connection remains open, and the server thread pins a CPU core at 100% utilization. By launching a small number of concurrent requests, an attacker can rapidly exhaust all available BEAM schedulers, rendering the entire application completely unresponsive.
The primary impact of GHSA-4W98-XF39-23GP is a total loss of application availability. The infinite loop consumes Erlang scheduler cycles, preventing the system from processing new connections or completing existing ones. Given the extreme ease of exploitation, a single attacker utilizing minimal bandwidth can systematically disable a production web server.
The vulnerability carries a CVSS v3.1 base score of 7.5 (High), reflected precisely by the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. The network attack vector and lack of authentication requirements maximize the exposure surface. The complexity is exceptionally low, as the attack requires no advanced timing, memory layout manipulation, or specific target configurations.
The scope of the vulnerability is completely localized to the ewe server process. It does not allow the attacker to compromise the underlying operating system, access the file system, or interact with other services. The strict separation of Erlang processes ensures that a crash in one application does not directly corrupt memory in another, though the severe CPU exhaustion affects the entire BEAM instance.
Environments relying on ewe for edge routing or critical API endpoints face immediate operational risks. Automated vulnerability scanners and botnets can easily integrate the static HTTP payload required to trigger the flaw. Consequently, timely patching is essential to maintain service reliability and uptime.
The definitive mitigation for this vulnerability is upgrading the ewe package to version 3.0.3 or later. The package maintainers have released versions 3.0.3, 3.0.4, and 3.0.5, all of which contain the corrected buffer management logic. Developers must update their gleam.toml dependencies and recompile their applications to apply the permanent fix.
For environments where immediate application updates are not feasible, network-level mitigations provide temporary protection. Reverse proxies (such as Nginx or HAProxy) positioned in front of the ewe server can be configured to strip trailers from incoming HTTP/1.1 requests or downgrade connections to HTTP/1.0, which does not support chunked transfer encoding at all.
Furthermore, Web Application Firewall (WAF) rules can be deployed to inspect chunked requests and explicitly block payloads containing forbidden trailers. Blocking any request where the Host, Transfer-Encoding, or Content-Length headers appear after the zero-length chunk will neutralize the most straightforward exploitation vectors. However, this approach requires complex rule configurations to accurately parse the chunked stream at the network edge.
Security teams can proactively detect vulnerable instances using active scanning tools. A carefully crafted HTTP request that includes a benign, undeclared trailer can be sent to the target server. If the server hangs and fails to return a response within a standard timeout window, the instance should be flagged as potentially vulnerable to GHSA-4W98-XF39-23GP.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
ewe vshakitskiy | < 3.0.3 | 3.0.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-835 |
| Attack Vector | Network |
| CVSS Score | 7.5 |
| Impact | High (Denial of Service) |
| Exploit Status | Proof of Concept Available |
| Authentication Required | None |
The program contains an iteration or loop with an exit condition that cannot be reached, i.e., an infinite loop.