Faraday affected by SSRF via protocol-relative URL host override in build_exclusive_url
Description
Faraday is an HTTP client library abstraction layer that provides a common interface over many adapters. Prior to 2.14.1, Faraday's build_exclusive_url method (in lib/faraday/connection.rb) uses Ruby's URI#merge to combine the connection's base URL with a user-supplied path. Per RFC 3986, protocol-relative URLs (e.g. //evil.com/path) are treated as network-path references that override the base URL's host/authority component. This means that if any application passes user-controlled input to Faraday's get(), post(), build_url(), or other request methods, an attacker can supply a protocol-relative URL like //attacker.com/endpoint to redirect the request to an arbitrary host, enabling Server-Side Request Forgery (SSRF). This vulnerability is fixed in 2.14.1.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Faraday before 2.14.1 allows SSRF via protocol-relative URLs due to unsafe use of URI#merge.
Vulnerability
Overview Faraday's build_exclusive_url method uses Ruby's URI#merge to combine a base URL with a user-supplied path. Per RFC 3986, protocol-relative URLs (e.g., //evil.com/path) are treated as network-path references, overriding the base URL's authority component [1]. An attacker can supply an input like //attacker.com/endpoint to redirect the request to an arbitrary host.
Exploitation
Any application that passes user-controlled input to Faraday's get(), post(), build_url(), or similar methods is vulnerable. No authentication is required to exploit; the attacker only needs to control the path or query parameters. Since Faraday abstracts many HTTP adapters, the behavior is independent of the underlying adapter.
Impact
Successful exploitation enables Server-Side Request Forgery (SSRF). An attacker can make the server issue requests to internal or external hosts, potentially accessing sensitive services, bypassing firewalls, or performing network reconnaissance. The vulnerability has a CVSS score of 7.5 (High) according to NVD [3].
Mitigation
The issue is fixed in Faraday version 2.14.1 [4]. Users should upgrade immediately. No workaround is available; using relative paths only would avoid the attack vector but may break functionality.
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
faradayRubyGems | >= 2.0.0, < 2.14.1 | 2.14.1 |
faradayRubyGems | >= 1.0.0, < 1.10.5 | 1.10.5 |
Affected products
2<2.14.1+ 1 more
- (no CPE)range: <2.14.1
- (no CPE)range: < 2.14.1
Patches
13 files changed · +37 −3
lib/faraday/connection.rb+3 −2 modified@@ -481,8 +481,9 @@ def build_exclusive_url(url = nil, params = nil, params_encoder = nil) if url && !base.path.end_with?('/') base.path = "#{base.path}/" # ensure trailing slash end - # Ensure relative url will be parsed correctly (such as `service:search` ) - url = "./#{url}" if url.respond_to?(:start_with?) && !url.start_with?('http://', 'https://', '/', './', '../') + # Ensure relative url will be parsed correctly (such as `service:search` or `//evil.com`) + url = "./#{url}" if url.respond_to?(:start_with?) && + (!url.start_with?('http://', 'https://', '/', './', '../') || url.start_with?('//')) uri = url ? base + url : base if params uri.query = params.to_query(params_encoder || options.params_encoder)
.rubocop_todo.yml+1 −1 modified@@ -31,7 +31,7 @@ Metrics/AbcSize: # Offense count: 3 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 230 + Max: 235 # Offense count: 9 # Configuration parameters: AllowedMethods, AllowedPatterns.
spec/faraday/connection_spec.rb+33 −0 modified@@ -311,6 +311,39 @@ def decode(params) end end + context 'with protocol-relative URL (GHSA-33mh-2634-fwr2)' do + it 'does not allow host override with //evil.com/path' do + conn.url_prefix = 'http://httpbingo.org/api' + uri = conn.build_exclusive_url('//evil.com/path') + expect(uri.host).to eq('httpbingo.org') + end + + it 'does not allow host override with //evil.com:8080/path' do + conn.url_prefix = 'http://httpbingo.org/api' + uri = conn.build_exclusive_url('//evil.com:8080/path') + expect(uri.host).to eq('httpbingo.org') + end + + it 'does not allow host override with //user:pass@evil.com/path' do + conn.url_prefix = 'http://httpbingo.org/api' + uri = conn.build_exclusive_url('//user:pass@evil.com/path') + expect(uri.host).to eq('httpbingo.org') + end + + it 'does not allow host override with ///evil.com' do + conn.url_prefix = 'http://httpbingo.org/api' + uri = conn.build_exclusive_url('///evil.com') + expect(uri.host).to eq('httpbingo.org') + end + + it 'still allows single-slash absolute paths' do + conn.url_prefix = 'http://httpbingo.org/api' + uri = conn.build_exclusive_url('/safe/path') + expect(uri.host).to eq('httpbingo.org') + expect(uri.path).to eq('/safe/path') + end + end + context 'with a custom `default_uri_parser`' do let(:url) { 'http://httpbingo.org' } let(:parser) { Addressable::URI }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
10- github.com/advisories/GHSA-33mh-2634-fwr2ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-25765ghsaADVISORY
- github.com/lostisland/faraday/commit/a6d3a3a0bf59c2ab307d0abd91bc126aef5561bcghsax_refsource_MISCWEB
- github.com/lostisland/faraday/pull/1569ghsaWEB
- github.com/lostisland/faraday/releases/tag/v1.10.5ghsaWEB
- github.com/lostisland/faraday/releases/tag/v2.14.1ghsax_refsource_MISCWEB
- github.com/lostisland/faraday/security/advisories/GHSA-33mh-2634-fwr2ghsax_refsource_CONFIRMWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/faraday/CVE-2026-25765.ymlghsaWEB
- www.rfc-editor.org/rfc/rfc3986ghsaWEB
- www.rfc-editor.org/rfc/rfc3986ghsaWEB
News mentions
0No linked articles in our index yet.