Skip to content

GHSA-9w88-79f8-m3vp CVE-2026-32881

Permissive List of Allowed Inputs in ewe

Medium Hex
Severity
5.3 / 10
Medium · CVSS 3.1
Exploit chance (EPSS)
0.39%
Chance of exploitation in the next 30 days. Higher than 33.53% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-183 Permissive List of Allowed Inputs
Fix
3.0.5
Upgrade ewe to this version or later

Description

Summary

ewe's chunked transfer encoding trailer handling merges declared trailer fields into req.headers after body parsing, but the denylist only blocks 9 header names. Security-sensitive headers like authorization, cookie, and x-forwarded-for can be injected or overwritten by a malicious client via trailers, potentially bypassing authentication or spoofing proxy-trust headers.

Impact

When ewe.read_body processes a chunked request with a Trailer header, it calls handle_trailers (ewe/internal/http1.gleam:493), which merges declared trailer fields into req.headers via request.set_header (line 517). The is_forbidden_trailer denylist (line 534) only blocks 9 header names: transfer-encoding, content-length, host, cache-control, expect, max-forwards, pragma, range, and te.

Security-sensitive headers are not blocked, including:

  • authorization — attacker can inject or overwrite Bearer tokens
  • cookie / set-cookie — attacker can inject session cookies
  • proxy-authorization — attacker can inject proxy credentials
  • x-forwarded-for, x-forwarded-host, x-forwarded-proto — attacker can spoof proxy-trust headers
  • x-real-ip — attacker can spoof client IP

A malicious client can inject these headers by declaring them in the Trailer request header and including them after the final 0\r\n chunk. If the header already exists (e.g., set by a reverse proxy), request.set_header overwrites it. Any application logic that reads these headers after calling ewe.read_body — such as authentication middleware, IP-based rate limiting, or session validation — will see the attacker-controlled values.

Proof of Concept

Inject an authorization header that didn't exist:

printf 'POST / HTTP/1.1\r\nHost: localhost:8080\r\nTransfer-Encoding: chunked\r\nTrailer: authorization\r\n\r\n4\r\ntest\r\n0\r\nauthorization: Bearer injected-token\r\n\r\n' | nc -w 2 localhost 8080

Overwrite a legitimate authorization header set by a proxy:

printf 'POST / HTTP/1.1\r\nHost: localhost:8080\r\nAuthorization: Bearer legitimate-token\r\nTransfer-Encoding: chunked\r\nTrailer: authorization\r\n\r\n4\r\ntest\r\n0\r\nauthorization: Bearer evil-token\r\n\r\n' | nc -w 2 localhost 8080

Inject x-forwarded-for to spoof client IP:

printf 'POST / HTTP/1.1\r\nHost: localhost:8080\r\nTransfer-Encoding: chunked\r\nTrailer: x-forwarded-for\r\n\r\n4\r\ntest\r\n0\r\nx-forwarded-for: 10.0.0.1\r\n\r\n' | nc -w 2 localhost 8080

Patches

  • Expand the denylist in is_forbidden_trailer to include authorization, cookie, set-cookie, proxy-authorization, x-forwarded-for, x-forwarded-host, x-forwarded-proto, x-real-ip, and other security-sensitive headers.
  • Alternatively, switch to an allowlist model that only permits explicitly safe trailer field names.

Affected versions

Hex

PackageVulnerableFixed in
ewe
>= 0.6.0, < 3.0.5
3.0.5

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

ewe Hex → 3.0.5

mix
{:ewe, "~> 3.0.5"} # then: mix deps.update ewe

Severity breakdown

CVSS 3.1 5.3

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
None

Weakness

CWE-183: Permissive List of Allowed Inputs

The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are explicitly allowed by policy because the inputs are assumed to be safe, but the list is too permissive - that is, it allows an input that is unsafe, leading to resultant weaknesses.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-x2w3-23jr-hrpf
ewe Has Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting)
Medium Also affects ewe
GHSA-4w98-xf39-23gp
Loop with Unreachable Exit Condition ('Infinite Loop') in ewe
High Also affects ewe
GHSA-h3rc-j82p-2c3h
vLLM: Untrusted EPS inputs can trigger denial of service or Ghostscript RCE
High Same weakness, CWE-183
GHSA-5hx5-vpf9-5wcv
pypdf: Unvalidated JPEG image data loading
Low Same weakness, CWE-183
GHSA-5qr9-xxm9-6cmq
Microsoft Security Advisory CVE-2026-96229 - .NET and Visual Studio Information Disclosure Vulnerability
Medium Same weakness, CWE-183
GHSA-f4gw-2p7v-4548
Axios: NO_PROXY bypass for 0.0.0.0 local addresses in axios
High Same weakness, CWE-183
GHSA-87qc-fj39-wccr
Glances: XML-RPC Multi-Origin CORS Configuration Silently Falls Back to Wildcard (Incomplete Fix for CVE-2026-33533)
High Same weakness, CWE-183
GHSA-g8m3-5g58-fq7m
undici vulnerable to Set-Cookie SameSite attribute downgrade via permissive substring matching
Low Same weakness, CWE-183
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor