VYPR
Unrated severityNVD Advisory· Published May 25, 2026

CRLF injection in cookie domain/path options in hackney

CVE-2026-47069

Description

Improper Neutralization of CRLF Sequences ('CRLF Injection') vulnerability in benoitc hackney allows HTTP Response Splitting. The hackney_cookie:setcookie/3 function in src/hackney_cookie.erl validates the Name and Value arguments against CRLF and control characters, but concatenates the domain and path options verbatim into the output iolist with no equivalent check. An attacker who controls either option — for example by supplying a Host header value forwarded as the cookie domain, or a request path forwarded as the cookie path — can inject a literal CRLF sequence and arbitrary additional Set-Cookie headers into the HTTP response.

This issue affects hackney: from 0.9.0 before 4.0.1.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CRLF injection in hackney_cookie:setcookie/3 allows HTTP response splitting via unvalidated domain/path options, affecting hackney 0.9.0 to 4.0.0.

Vulnerability

The vulnerability resides in the hackney_cookie:setcookie/3 function in src/hackney_cookie.erl. While the Name and Value arguments are validated against CRLF and control characters, the domain and path options are concatenated verbatim into the output iolist without equivalent checks. This affects hackney versions from 0.9.0 up to (but not including) 4.0.1 [1][2][3][4].

Exploitation

An attacker who controls either the domain or path option—for example, by supplying a Host header value forwarded as the cookie domain, or a request path forwarded as the cookie path—can inject a literal CRLF sequence and arbitrary additional Set-Cookie headers into the HTTP response. No authentication is required if the attacker can influence these options [2][4].

Impact

Successful exploitation enables HTTP response splitting, allowing an attacker to inject arbitrary cookies, perform session fixation, or strip Secure/HttpOnly flags from existing cookies. The CVSS v4.0 score is 2.1 (Low), reflecting the need for attacker-controlled input to reach the vulnerable options [2][4].

Mitigation

The issue is fixed in hackney version 4.0.1. The commit [3] adds validation for CR/LF, semicolon, and control characters in both domain and path options. Users should upgrade to 4.0.1 or later. No workaround is documented [1][3].

AI Insight generated on May 25, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Benoitc/Hackneyinferred2 versions
    >=0.9.0,<4.0.1+ 1 more
    • (no CPE)range: >=0.9.0,<4.0.1
    • (no CPE)range: >= 0.9.0, < 4.0.1

Patches

1
8e02b99c28ae

fix(security): validate cookie domain/path options (GHSA-mp55)

https://github.com/benoitc/hackneyBenoit ChesneauMay 20, 2026via body-scan
2 files changed · +32 2
  • src/hackney_cookie.erl+15 2 modified
    @@ -46,11 +46,24 @@ setcookie(Name, Value, Opts) ->
                   end,
       DomainBin = case lists:keyfind(domain, 1, Opts) of
                     false -> <<>>;
    -                {_, Domain} -> [<<"; Domain=">>, Domain]
    +                {_, Domain} ->
    +                  %% GHSA-mp55: Name/Value are guarded above; Domain and
    +                  %% Path must reject the same line-terminating bytes (and
    +                  %% ';', which would start a new attribute) so a
    +                  %% request-derived domain/path cannot inject a second
    +                  %% Set-Cookie header.
    +                  nomatch = binary:match(iolist_to_binary(Domain),
    +                                         [<<$;>>, <<$\s>>, <<$\t>>, <<$\r>>,
    +                                          <<$\n>>, <<$\013>>, <<$\014>>, <<0>>]),
    +                  [<<"; Domain=">>, Domain]
                   end,
       PathBin = case lists:keyfind(path, 1, Opts) of
                   false -> <<>>;
    -              {_, Path} -> [<<"; Path=">>, Path]
    +              {_, Path} ->
    +                nomatch = binary:match(iolist_to_binary(Path),
    +                                       [<<$;>>, <<$\r>>, <<$\n>>,
    +                                        <<$\013>>, <<$\014>>, <<0>>]),
    +                [<<"; Path=">>, Path]
                 end,
       SecureBin = case lists:keyfind(secure, 1, Opts) of
                     false -> <<>>;
    
  • test/hackney_cookie_tests.erl+17 0 modified
    @@ -99,3 +99,20 @@ setcookie_failures_test_() ->
         [{iolist_to_binary(io_lib:format("{~p, ~p} failure", [N, V])),
           fun() -> true = F(N, V) end}
          || {N, V} <- Tests].
    +
    +%% GHSA-mp55: domain/path options must reject CR/LF/VT/FF/';' so a
    +%% request-derived value cannot split the Set-Cookie header.
    +setcookie_domain_path_injection_test_() ->
    +    F = fun(Opts) ->
    +            try hackney_cookie:setcookie(<<"sid">>, <<"abc">>, Opts) of
    +                _ -> false
    +            catch _:_ -> true
    +            end
    +    end,
    +    Tests = [
    +            {"path CRLF", [{path, <<"/x\r\nSet-Cookie: admin=1; Path=/">>}]},
    +            {"path semicolon", [{path, <<"/x; Domain=evil">>}]},
    +            {"domain CRLF", [{domain, <<"x.example\r\nSet-Cookie: a=1">>}]},
    +            {"domain space", [{domain, <<"x.example evil">>}]}
    +            ],
    +    [{Name, fun() -> true = F(Opts) end} || {Name, Opts} <- Tests].
    

Vulnerability mechanics

Root cause

"Missing CRLF and control-character validation on the `domain` and `path` options in `hackney_cookie:setcookie/3` allows HTTP response splitting."

Attack vector

An attacker who controls the `domain` or `path` option passed to `hackney_cookie:setcookie/3` can inject a literal CRLF sequence (`\r\n`) followed by arbitrary `Set-Cookie` header content [ref_id=2]. This is realistic when the cookie domain is derived from the `Host` header, the cookie path is derived from the request URI, or a `Location` path is copied into a cookie [ref_id=2]. The injected CRLF splits the HTTP response header, allowing the attacker to add a second `Set-Cookie` header (e.g., `admin=1`) that can overwrite session cookies or strip security flags [ref_id=2].

Affected code

The vulnerability resides in `src/hackney_cookie.erl`, specifically in the `hackney_cookie:setcookie/3` function. The `DomainBin` and `PathBin` clauses (lines 47 and 51 of the original file) concatenate the `domain` and `path` options directly into the output iolist without any CRLF or control-character validation [ref_id=2]. The `Name` and `Value` arguments are guarded by a `binary:match` rejection set, but the domain and path options bypass that check entirely [ref_id=2].

What the fix does

The patch [patch_id=2473712] adds a `binary:match` guard to both the `Domain` and `Path` clauses in `hackney_cookie:setcookie/3`, rejecting the same set of dangerous bytes already blocked for `Name` and `Value`: `;`, `\r`, `\n`, `\013` (vertical tab), `\014` (form feed), and null byte `0` [ref_id=1]. The domain clause additionally rejects space and tab characters [ref_id=1]. If any of these bytes appear in the domain or path option, the match raises a `nomatch` exception, preventing the CRLF injection from reaching the output iolist [patch_id=2473712].

Preconditions

  • inputThe attacker must control the value passed as the `domain` or `path` option to `hackney_cookie:setcookie/3`
  • configThe caller must derive the domain or path option from attacker-influenced request data (e.g., Host header, request URI)

Reproduction

Call `hackney_cookie:setcookie(&lt;&lt;"sid"&gt;&gt;, &lt;&lt;"abc"&gt;&gt;, [{path, &lt;&lt;"/x\r\nSet-Cookie: admin=1; Path=/"&gt;&gt;}])`. The returned binary contains a literal `\r\n` followed by a second `Set-Cookie:` line. When written into an HTTP response header, the client parses two headers, including `admin=1` [ref_id=2].

Generated on May 25, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.