Apr 8, 2026·5 min read·9 visits
Hono versions prior to 4.12.12 do not sanitize cookie names in the `setCookie` utility, leading to CRLF injection. Attackers can exploit this to inject arbitrary HTTP headers or split the response, provided the application uses dynamic user input for cookie names. Upgrading to version 4.12.12 resolves the vulnerability.
The Hono web framework contains a vulnerability in its cookie management utility that allows HTTP response splitting. The `setCookie` function fails to validate or sanitize user-supplied cookie names against control characters. If an application utilizes untrusted input to define a cookie name, an attacker can inject carriage return and line feed (CRLF) characters to manipulate the raw HTTP response headers.
The Hono web framework provides a utility for managing HTTP cookies. Developers rely on the setCookie function to instruct clients to store stateful information. This function is part of the hono/cookie module and handles the serialization of cookie names, values, and attributes into a standard HTTP header format.
Vulnerability GHSA-26PP-8WGV-HJVM exists because this serialization process fails to sanitize input. Specifically, the framework does not strip or validate carriage return and line feed characters before appending them to the HTTP response stream. This flaw falls under CWE-113, Improper Neutralization of CRLF Sequences in HTTP Headers.
Applications are vulnerable if they dynamically generate cookie names based on untrusted user input. An attacker can exploit this behavior to inject arbitrary HTTP headers into the server's response. This leads to HTTP response splitting, which undermines the integrity of the client-server communication channel.
The defect originates in the internal _serialize function located in src/utils/cookie.ts. This function takes a cookie name, value, and options object, returning a formatted string for the Set-Cookie header. The vulnerable implementation directly interpolates the name and value arguments into a template string.
The code executes let cookie = \${name}=${value}`without prior validation of thenameargument. According to RFC 6265, a cookie name must be a valid token, meaning it cannot contain control characters or separators like equals signs and semicolons. The_serialize` function erroneously assumes the caller provides a compliant token.
When an application passes an untrusted string as the cookie name, the unvalidated input becomes part of the HTTP header. The HTTP protocol uses carriage return (\r or %0D) and line feed (\n or %0A) characters to separate distinct headers. By including these characters in the cookie name, the input breaks out of the Set-Cookie context.
The vulnerable implementation lacked any conditional checks on the input string. The code immediately generated the cookie string using string interpolation. This approach trusted that developers would only use static or pre-validated strings for cookie names.
The patch introduced in commit a586cd72e3f6122792e631ecf1817e5cabb803ec implements strict input validation. The maintainer added a regular expression, validCookieNameRegEx, which verifies that the cookie name only contains characters permitted by the RFC 6265 token specification.
// Patched implementation in src/utils/cookie.ts
const _serialize = (name: string, value: string, opt: CookieOptions = {}): string => {
+ if (!validCookieNameRegEx.test(name)) {
+ throw new Error('Invalid cookie name')
+ }
+
let cookie = `${name}=${value}`
// ...
}If the input contains forbidden characters, including \r and \n, the function immediately throws an error. This prevents the execution flow from reaching the string interpolation step. The test cases added alongside the patch confirm that supplying strings like legit\r\nX-Injected: evil correctly triggers the validation error. The fix completely eliminates the CRLF injection vector at the framework level.
Exploitation requires the target application to accept user input and use it as the first argument to the setCookie function. While applications commonly store user input in cookie values, using user input for cookie names is an uncommon pattern. If this condition is met, the attacker sends a crafted payload containing CRLF characters.
A standard exploit payload injects a new header by breaking the current line. The payload user_pref\r\nLocation: http://malicious.com begins with a benign string, followed by the CRLF sequence, and then the injected header. When the application processes this input, the resulting HTTP response contains a Set-Cookie header that terminates early.
The framework generates the following raw HTTP response stream:
HTTP/1.1 200 OK
Set-Cookie: user_pref
Location: http://malicious.com=valueThe HTTP client parses the injected Location header as a legitimate directive from the server. This specific payload results in an unvalidated redirect, forcing the victim's browser to navigate to an attacker-controlled domain. The = character from the original template literal becomes part of the injected header's value, which is often ignored by the client parser.
The primary impact is HTTP Response Splitting and Header Injection. The severity is constrained by the prerequisite that the application must use dynamic, user-controllable data for cookie names. In scenarios where this prerequisite is satisfied, the attacker gains significant control over the client's interaction with the application.
Header injection allows attackers to manipulate security controls. An attacker can inject a Set-Cookie header to perform session fixation or overwrite existing session identifiers. They can also inject a Content-Security-Policy header to weaken protections, enabling secondary attacks like Cross-Site Scripting (XSS).
In severe cases, an attacker can use a double CRLF sequence (\r\n\r\n) to terminate the header section entirely. This allows them to inject arbitrary content into the response body. If the application sits behind a caching proxy, this technique can poison the cache, causing the proxy to serve the malicious payload to subsequent visitors.
The vulnerability is resolved in Hono version 4.12.12. Administrators and developers must update the hono package to this version or a later release. The patch is entirely backward compatible for applications using compliant cookie names.
If an immediate upgrade is not feasible, developers must implement strict validation on any user input used in HTTP responses. Input used for cookie names must be validated against an allowlist of alphanumeric characters. Applications should never permit control characters or separators in cookie names.
Network defenders can deploy Web Application Firewall (WAF) rules to inspect inbound traffic for anomalous CRLF sequences. Rules should block requests containing URL-encoded carriage return (%0D) or line feed (%0A) characters in parameters known to influence HTTP headers. This provides a temporary defense-in-depth measure.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
hono Hono | < 4.12.12 | 4.12.12 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | HTTP Response Splitting / CRLF Injection |
| CWE ID | CWE-113, CWE-93 |
| Affected Component | hono/cookie (setCookie utility) |
| Exploit Status | Proof of Concept available |
| CVSS Score | 5.3 (Moderate) |
| Attack Vector | Network |
Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')