VYPR
Medium severity6.5NVD Advisory· Published Feb 11, 2025· Updated Apr 29, 2026

CVE-2025-1211

CVE-2025-1211

Description

Versions of the package hackney before 1.21.0 are vulnerable to Server-side Request Forgery (SSRF) due to improper parsing of URLs by URI built-in module and hackey. Given the URL http://127.0.0.1?@127.2.2.2/, the URI function will parse and see the host as 127.0.0.1 (which is correct), and hackney will refer the host as 127.2.2.2/. This vulnerability can be exploited when users rely on the URL function for host checking.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
hackneyHex
< 1.21.01.21.0

Patches

2
9594ce58fabd

Merge pull request #753 from tank-bohr/cve-2025-1211

https://github.com/benoitc/hackneyBenoit ChesneauFeb 14, 2025via ghsa
2 files changed · +41 11
  • src/hackney_url.erl+15 11 modified
    @@ -52,22 +52,24 @@ parse_url(URL) ->
       parse_url(URL, #hackney_url{transport=hackney_tcp, scheme=http}).
     
     parse_url(URL, S) ->
    -  {URL1, Fragment} =  parse_fragment(URL),
    -  case binary:split(URL1, <<"/">>) of
    -    [URL1] ->
    -      parse_addr1(URL1, S#hackney_url{raw_path = raw_fragment(Fragment),
    +  {URL1, Fragment} = cut_fragment(URL),
    +  {URL2, Query} = cut_query(URL1),
    +  RawPath = << (raw_query(Query))/binary, (raw_fragment(Fragment))/binary >>,
    +  case binary:split(URL2, <<"/">>) of
    +    [URL2] ->
    +      parse_addr1(URL2, S#hackney_url{raw_path = RawPath,
                                           path = <<>>,
    +                                      qs = Query,
                                           fragment = Fragment});
         [Addr] ->
           Path = <<"/">>,
    -      parse_addr1(Addr, S#hackney_url{raw_path = << Path/binary, (raw_fragment(Fragment))/binary >>,
    +      parse_addr1(Addr, S#hackney_url{raw_path = << Path/binary, RawPath/binary >>,
                                           path = Path,
    +                                      qs = Query,
                                           fragment = Fragment});
         [Addr, Path] ->
    -      RawPath =  <<"/", Path/binary, (raw_fragment(Fragment))/binary >>,
    -      {Path1, Query} = parse_path( << "/", Path/binary >>),
    -      parse_addr(Addr, S#hackney_url{raw_path = RawPath,
    -                                     path = Path1,
    +      parse_addr(Addr, S#hackney_url{raw_path = <<"/", Path/binary, RawPath/binary >>,
    +                                     path = <<"/", Path/binary >>,
                                          qs = Query,
                                          fragment = Fragment})
       end.
    @@ -76,6 +78,8 @@ parse_url(URL, S) ->
     raw_fragment(<<"">>) -> <<"">>;
     raw_fragment(Fragment) -> <<"#", Fragment/binary>>.
     
    +raw_query(<<>>) -> <<>>;
    +raw_query(Query) -> <<"?", Query/binary>>.
     
     property(transport, URL) -> URL#hackney_url.transport;
     property(scheme, URL) -> URL#hackney_url.scheme;
    @@ -261,15 +265,15 @@ parse_netloc(Netloc, #hackney_url{transport=Transport}=S) ->
       end.
     
     
    -parse_path(Path) ->
    +cut_query(Path) ->
       case binary:split(Path, <<"?">>) of
         [_Path] ->
           {Path, <<>>};
         [Path1, Query] ->
           {Path1, Query}
       end.
     
    -parse_fragment(S) ->
    +cut_fragment(S) ->
       case binary:split(S, <<"#">>) of
         [_S] ->
           {S, <<>>};
    
  • test/hackney_url_tests.erl+26 0 modified
    @@ -286,6 +286,32 @@ parse_url_test_() ->
                               port = 80,
                               user = <<"">>,
                               password = <<"">>}
    +            },
    +            {<<"https://example.com/foo/bar">>,
    +             #hackney_url{transport = hackney_ssl,
    +                          scheme = https,
    +                          netloc = <<"example.com">>,
    +                          raw_path = <<"/foo/bar">>,
    +                          path = <<"/foo/bar">>,
    +                          qs = <<>>,
    +                          fragment = <<>>,
    +                          host = "example.com",
    +                          port = 443,
    +                          user = <<>>,
    +                          password = <<>>}
    +            },
    +            {<<"http://127.0.0.1?@127.2.2.2/">>,
    +             #hackney_url{transport = hackney_tcp,
    +                          scheme = http,
    +                          netloc = <<"127.0.0.1">>,
    +                          raw_path = <<"?@127.2.2.2/">>,
    +                          path = <<>>,
    +                          qs = <<"@127.2.2.2/">>,
    +                          fragment = <<>>,
    +                          host = "127.0.0.1",
    +                          port = 80,
    +                          user = <<>>,
    +                          password = <<>>}
                 }
                 ],
         [{V, fun() -> R = hackney_url:parse_url(V) end} || {V, R} <- Tests].
    

Vulnerability mechanics

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

References

7

News mentions

0

No linked articles in our index yet.