CVE-2026-34715
ewe Has Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting)
ewe is a Gleam web server. Prior to version 3.0.6, the encode_headers function in src/ewe/internal/encoder.gleam directly interpolates response header keys and values into raw HTTP bytes without validating or stripping CRLF (\r\n) sequences. An application that passes user-controlled data into response headers (e.g., setting a Location redirect header from a request parameter) allows an attacker to inject arbitrary HTTP response content, leading to response splitting, cache poisoning, and possible cross-site scripting. Notably, ewe does validate CRLF in incoming request headers via validate_field_value() in the HTTP/1.1 parser — but provides no equivalent protection for outgoing response headers in the encoder. This issue has been patched in version 3.0.6.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
5.3
ewe Has Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting)
ewe is a Gleam web server. Prior to version 3.0.6, the encode_headers function in src/ewe/internal/encoder.gleam directly interpolates response header keys and values into raw HTTP bytes without validating or stripping CRLF (\r\n) sequences. An application that passes user-controlled data into response headers (e.g., setting a Location redirect header from a request parameter) allows an attacker to inject arbitrary HTTP response content, leading to response splitting, cache poisoning, and possible cross-site scripting. Notably, ewe does validate CRLF in incoming request headers via validate_field_value() in the HTTP/1.1 parser — but provides no equivalent protection for outgoing response headers in the encoder. This issue has been patched in version 3.0.6.
- Record
CVE-2026-34715- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-113
- Updated
- 2026-11-02
EUVDEUVD-2026-18468
5.3
ewe is a Gleam web server. Prior to version 3.0.6, the encode_headers function in src/ewe/internal/encoder.gleam directly interpolates response header keys and values into raw HTTP bytes without validating or stripping CRLF (\r\n) sequences. An application that passes user-controlled data into response headers (e.g., setting a Location redirect header from a request parameter) allows an attacker to inject arbitrary HTTP response content, leading to response splitting, cache poisoning, and possible cross-site scripting. Notably, ewe does validate CRLF in incoming request headers via validate_field_value() in the HTTP/1.1 parser — but provides no equivalent protection for outgoing response headers in the encoder. This issue has been patched in version 3.0.6.
- Record
EUVD-2026-18468- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-x2w3-23jr-hrpf
5.3
ewe Has Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting)
Summary
The encode_headers function in src/ewe/internal/encoder.gleam directly interpolates response header keys and values into raw HTTP bytes without validating or stripping CRLF (\r\n) sequences. An application that passes user-controlled data into response headers (e.g., setting a Location redirect header from a request parameter) allows an attacker to inject arbitrary HTTP response content, leading to response splitting, cache poisoning, and possible cross-site scripting.
Notably, ewe does validate CRLF in incoming request headers via validate_field_value() in the HTTP/1.1 parser — but provides no equivalent protection for outgoing response headers in the encoder.
Details
File: src/ewe/internal/encoder.gleam
Vulnerable code:
fn encode_headers(headers: List(#(String, String))) -> BitArray {
let headers =
list.fold(headers, <<>>, fn(acc, headers) {
let #(key, value) = headers
<<acc:bits, key:utf8, ": ", value:utf8, "\r\n">>
})
<<headers:bits, "\r\n">>
}
Both key and value are embedded directly into the BitArray output. If either contains \r\n, the resulting bytes become a structurally valid but attacker-controlled HTTP response, terminating the current header early and injecting new headers or a second HTTP response.
Contrast with request parsing (src/ewe/internal/http1.gleam): incoming header values are protected:
use value <- try(
validate_field_value(value) |> replace_error(InvalidHeaders)
)
No analogous validation exists for outgoing header values in the encoder. The solution is to strip or reject \r (0x0D) and \n (0x0A) from all header key and value strings in encode_headers before encoding, mirroring the validation already applied to incoming request headers via validate_field_value()
PoC
An ewe application echoes a user-supplied redirect URL into a Location header:
fn handle_request(req: Request) -> Response {
let redirect_url =
request.get_query(req)
|> result.try(list.key_find(_, "next"))
|> result.unwrap("/home")
response.new(302)
|> response.set_header("location", redirect_url)
|> response.set_body(ewe.Empty)
}
Attacker request:
printf 'GET /?next=https://example.com%%0d%%0aX-Injected:%%20true HTTP/1.1\r\nHost: localhost\r\n\r\n' | nc -w 2 localhost 8080
Resulting response:
HTTP/1.1 302 Found
location: https://example.com
X-Injected: true
content-length: 0
date: Tue, 24 Mar 2026 07:53:00 GMT
connection: keep-alive
The X-Injected: true header appears as a separate response header, confirming that CRLF sequences in user input are not sanitized by the encoder.
- Record
GHSA-x2w3-23jr-hrpf- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-113
- Updated
- 2026-11-02
NVD
5.3
ewe is a Gleam web server. Prior to version 3.0.6, the encode_headers function in src/ewe/internal/encoder.gleam directly interpolates response header keys and values into raw HTTP bytes without validating or stripping CRLF (\r\n) sequences. An application that passes user-controlled data into response headers (e.g., setting a Location redirect header from a request parameter) allows an attacker to inject arbitrary HTTP response content, leading to response splitting, cache poisoning, and possible cross-site scripting. Notably, ewe does validate CRLF in incoming request headers via validate_field_value() in the HTTP/1.1 parser — but provides no equivalent protection for outgoing response headers in the encoder. This issue has been patched in version 3.0.6.
- Record
CVE-2026-34715- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-113
- Updated
- 2026-11-02
OSV
5.3
ewe Has Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting)
ewe is a Gleam web server. Prior to version 3.0.6, the encode_headers function in src/ewe/internal/encoder.gleam directly interpolates response header keys and values into raw HTTP bytes without validating or stripping CRLF (\r\n) sequences. An application that passes user-controlled data into response headers (e.g., setting a Location redirect header from a request parameter) allows an attacker to inject arbitrary HTTP response content, leading to response splitting, cache poisoning, and possible cross-site scripting. Notably, ewe does validate CRLF in incoming request headers via validate_field_value() in the HTTP/1.1 parser — but provides no equivalent protection for outgoing response headers in the encoder. This issue has been patched in version 3.0.6.
- Record
CVE-2026-34715- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-113
- Updated
- 2026-11-02
OSVGHSA-x2w3-23jr-hrpf
5.3
ewe Has Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting)
Summary
The encode_headers function in src/ewe/internal/encoder.gleam directly interpolates response header keys and values into raw HTTP bytes without validating or stripping CRLF (\r\n) sequences. An application that passes user-controlled data into response headers (e.g., setting a Location redirect header from a request parameter) allows an attacker to inject arbitrary HTTP response content, leading to response splitting, cache poisoning, and possible cross-site scripting.
Notably, ewe does validate CRLF in incoming request headers via validate_field_value() in the HTTP/1.1 parser — but provides no equivalent protection for outgoing response headers in the encoder.
Details
File: src/ewe/internal/encoder.gleam
Vulnerable code:
fn encode_headers(headers: List(#(String, String))) -> BitArray {
let headers =
list.fold(headers, <<>>, fn(acc, headers) {
let #(key, value) = headers
<<acc:bits, key:utf8, ": ", value:utf8, "\r\n">>
})
<<headers:bits, "\r\n">>
}
Both key and value are embedded directly into the BitArray output. If either contains \r\n, the resulting bytes become a structurally valid but attacker-controlled HTTP response, terminating the current header early and injecting new headers or a second HTTP response.
Contrast with request parsing (src/ewe/internal/http1.gleam): incoming header values are protected:
use value <- try(
validate_field_value(value) |> replace_error(InvalidHeaders)
)
No analogous validation exists for outgoing header values in the encoder. The solution is to strip or reject \r (0x0D) and \n (0x0A) from all header key and value strings in encode_headers before encoding, mirroring the validation already applied to incoming request headers via validate_field_value()
PoC
An ewe application echoes a user-supplied redirect URL into a Location header:
fn handle_request(req: Request) -> Response {
let redirect_url =
request.get_query(req)
|> result.try(list.key_find(_, "next"))
|> result.unwrap("/home")
response.new(302)
|> response.set_header("location", redirect_url)
|> response.set_body(ewe.Empty)
}
Attacker request:
printf 'GET /?next=https://example.com%%0d%%0aX-Injected:%%20true HTTP/1.1\r\nHost: localhost\r\n\r\n' | nc -w 2 localhost 8080
Resulting response:
HTTP/1.1 302 Found
location: https://example.com
X-Injected: true
content-length: 0
date: Tue, 24 Mar 2026 07:53:00 GMT
connection: keep-alive
The X-Injected: true header appears as a separate response header, confirming that CRLF sequences in user input are not sanitized by the encoder.
- Record
GHSA-x2w3-23jr-hrpf- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-113
- Updated
- 2026-11-02
Affected products
Affected packages
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-34715 is a medium vulnerability (CVSS 5.3) in Vshakitskiy Ewe, published April 1, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.34%, the 27th percentile. Fixed in ewe 3.0.6.
References
github.com/vshakitskiy/ewe/security/advisories/GHSA-x2w3-23jr-hrpf
github.com/vshakitskiy/ewe/commit/ce4ff214d32626a10fda9398dc94a2d720e17446
github.com/vshakitskiy/ewe/releases/tag/v3.0.6
nvd.nist.gov/vuln/detail/CVE-2026-34715
github.com/advisories/GHSA-x2w3-23jr-hrpf
github.com/CVEProject/cvelistV5/tree/main/cves/2026/34xxx/CVE-2026-34715.json
github.com/vshakitskiy/ewe