Skip to content

CVE-2026-25765: Verified Repro With Script Download

CVE-2026-25765: Faraday: SSRF via protocol-relative URL overriding base authority

CVE-2026-25765 is verified against faraday · rubygems. Affected versions: faraday >= 1.0.0, <= 1.10.4 and >= 2.0.0, <= 2.14.0. Vulnerability class: SSRF. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00147.

REPRO-2026-00147 faraday · rubygems SSRF May 22, 2026 CVE entry ↗ .txt
Severity
MEDIUM
CVSS
5.8
Reproduced in
10m 15s
Tool calls
128
Spend
$0.67
01 · Overview

What Is CVE-2026-25765?

CVE-2026-25765 (GHSA-33mh-2634-fwr2) is a medium-severity server-side request forgery (SSRF, CWE-918) vulnerability in the Ruby faraday HTTP client, where a protocol-relative request path can override the connection's configured base host. Pruva reproduced it (reproduction REPRO-2026-00147).

02 · Severity & CVSS

CVE-2026-25765 Severity & CVSS Score

CVE-2026-25765 is rated medium severity, with a CVSS base score of 5.8 out of 10.

MEDIUM threat level
5.8 / 10 CVSS base
Weakness CWE-918 (Server-Side Request Forgery) — Server-Side Request Forgery (SSRF)

Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.

03 · Affected Versions

Affected faraday Versions

faraday · rubygems versions faraday >= 1.0.0, <= 1.10.4 and >= 2.0.0, <= 2.14.0 are affected.

How to Reproduce CVE-2026-25765

$ pruva-verify REPRO-2026-00147
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00147/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-25765

Reproduced by Pruva's autonomous agents — 128 tool calls over 10 min. Full root-cause analysis and the complete transcript are below.

How the agent worked 439 events · 128 tool calls · 10 min
10 minDuration
128Tool calls
102Reasoning steps
439Events
1Dead-ends
Agent activity over 10 min
Support
17
Repro
190
Variant
227
0:0010:15

Root Cause and Exploit Chain for CVE-2026-25765

Summary

The faraday Ruby HTTP client library contained a Server-Side Request Forgery (SSRF) vulnerability in its build_exclusive_url method. When a connection was configured with a trusted base URL (e.g., http://safe.local/api) and a request path starting with // (a protocol-relative or "network-path" reference) was supplied, the // prefix incorrectly passed the existing relative-URL guard. Ruby's URI#+ then interpreted the protocol-relative path as an authority override, replacing the base host with the attacker-specified host. This allowed an attacker-controlled path string to redirect outbound requests to arbitrary hosts, bypassing the intended scope of the Faraday connection.

Impact

  • Package: faraday (RubyGems)
  • Affected versions: 1.0.01.10.4 and 2.0.02.14.0
  • Fixed versions: 1.10.5 and 2.14.1
  • CWE: CWE-918 (Server-Side Request Forgery)
  • Risk: Medium — CVSS 5.8
  • Consequences: Any application that forwards user-influenced path strings to a Faraday connection without additional validation can be tricked into making requests to internal or attacker-controlled hosts, potentially exposing internal services, cloud metadata endpoints, or allowing request-smuggling attacks.

Root Cause

The vulnerable code lives in lib/faraday/connection.rb inside the build_exclusive_url method.

Vulnerable guard (v2.14.0):

url = "./#{url}" if url.respond_to?(:start_with?) && !url.start_with?('http://', 'https://', '/', './', '../')

Because a protocol-relative URL such as //evil.com/path begins with /, the guard condition !url.start_with?('/') evaluates to false, so the URL is not prefixed with ./. When URI#+ merges the base URL (http://safe.local) with //evil.com/path, RFC 3986 dictates that the authority component of the merge target overrides the base authority. The resulting URI becomes http://evil.com/path, completely leaving the configured base host.

Fix commit: a6d3a3a0bf59c2ab307d0abd91bc126aef5561bc

Fixed guard (v2.14.1):

url = "./#{url}" if url.respond_to?(:start_with?) &&
                    (!url.start_with?('http://', 'https://', '/', './', '../') || url.start_with?('//'))

The fix explicitly detects the // prefix and prepends ./, neutralising the authority component. The merged URI then stays scoped to the base host (http://safe.local///evil.com/path), preventing host override.

Reproduction Steps

  1. Run repro/reproduction_steps.sh.
  2. The script installs the vulnerable (2.14.0) and fixed (2.14.1) gem versions.
  3. It starts a local TCP listener on an ephemeral port to stand in for the attacker host.
  4. For each version it:
    • Creates a Faraday connection with base URL http://192.0.2.1 (TEST-NET-1, guaranteed non-routable).
    • Calls build_exclusive_url('//127.0.0.1:<port>/x') and records the resulting host.
    • Issues an actual HTTP GET with the same protocol-relative path.
    • Counts how many requests the local listener received.
  5. Expected evidence:
    • Vulnerable (2.14.0): built_host is 127.0.0.1, the request succeeds with status 404, and the local listener receives ≥1 request.
    • Fixed (2.14.1): built_host remains 192.0.2.1, the request fails with Connection refused, and the local listener receives 0 requests.

Evidence

  • logs/vulnerable.json — Faraday 2.14.0 runtime results:
    {
      "built_url": "http://127.0.0.1:33953/x",
      "built_host": "127.0.0.1",
      "request_status": 404,
      "request_success": true
    }
    
  • logs/fixed.json — Faraday 2.14.1 runtime results:
    {
      "built_url": "http://192.0.2.1///127.0.0.1:33953/x",
      "built_host": "192.0.2.1",
      "request_error": "Faraday::ConnectionFailed: Failed to open TCP connection to 192.0.2.1:80 (Connection refused - connect(2) for \"192.0.2.1\" port 80)",
      "request_success": false
    }
    
  • repro/runtime_manifest.json — consolidated verdict:
    {
      "verdict": "confirmed",
      "vulnerable_version": "2.14.0",
      "fixed_version": "2.14.1",
      "vulnerable_built_host": "127.0.0.1",
      "fixed_built_host": "192.0.2.1",
      "vulnerable_request_succeeded": true,
      "fixed_request_succeeded": false,
      "vulnerable_listener_requests": 2,
      "fixed_listener_requests": 0
    }
    

Recommendations / Next Steps

  • Upgrade: Update faraday to >= 1.10.5 or >= 2.14.1 immediately.
  • Input validation: Applications accepting user-influenced URL paths should validate that paths do not begin with // before passing them to Faraday, as a defense-in-depth measure.
  • Regression testing: Add unit tests that assert build_exclusive_url rejects host override for //evil.com, //evil.com:8080, //user:pass@evil.com, and ///evil.com (all covered by the upstream spec added in the fix commit).
  • Network segmentation: Where SSRF risk is high, restrict outbound connectivity from application servers to only required destinations.

Additional Notes

  • Idempotency: repro/reproduction_steps.sh was executed twice consecutively and produced identical verdicts both times.
  • Edge cases: The reproduction script uses 192.0.2.1 (RFC 5737 TEST-NET-1) as the base host to guarantee the fixed version fails predictably with Connection refused rather than relying on DNS non-resolution, which can be unreliable in environments with wildcard DNS or ISP hijacking.
  • Server log: The local HTTP listener received 2 requests during the vulnerable test and 0 requests during the fixed test, providing direct runtime proof that the protocol-relative path was neutralised by the patch.

CVE-2026-25765 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:000:31
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-25765 · cve-2026
0:02
0:02
0:04
web search
0:05
0:08
web search
0:22
0:22
extract_facts
no facts extracted
0:23
0:23
0:23
supportrepro
0:25
0:25
0:25
0:26
0:26
0:26
0:29
0:30
$git clone --depth=100 https://github.com/lostisland/faraday.git faraday_repo
1.3s
Cloning into 'faraday_repo'...
0:31
0:31
$cd faraday_repo && git show a6d3a3a0bf59c2ab307d0abd91bc126aef5561bc
{"cwd":"/root/.pruva/runs/cve-2026-25765_20260522-175117","duration_ms":5,"exit_code":0,"stderr":"","stdout":"commit a6d3a3a0bf59c2ab307d0abd91bc126aef5561bc\nAuthor: Matt <iMacTia@users.noreply.github.com>\nDate:   Sat Feb 7 15:11:41 2026 +0000\n\n    Merge commit from fork\n    \n    Protocol-relative URLs (e.g. `//evil.com/path`) bypassed the existing\n    relative-URL guard in `build_exclusive_url`, allowing an attacker-controlled\n    URL to override the connection's base host. The `//` prefix matched the\n    `/` check in `start_with?`, so these URLs were passed through to\n    `URI#+` which treated them as authority references, replacing the host.\n    \n    Extend the guard condition so that URLs starting with `//` are also\n    prefixed with `./`, neutralising the authority component and keeping\n    requests scoped to the configured base host.\n    \n    Security: GHSA-33mh-2634-fwr2\n    \n    Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>\n\ndiff --git a/.rubocop_todo.yml b/.rubocop_todo.yml\nindex f3d0f2e..3f56b48 100644\n--- a/.rubocop_todo.yml\n+++ b/.rubocop_todo.yml\n@@ -31,7 +31,7 @@ Metrics/AbcSize:\n # Offense count: 3\n # Configuration parameters: Coun… [truncated]

Artifacts and Evidence for CVE-2026-25765

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2026-25765

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-25765 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-25765

How does the CVE-2026-25765 SSRF attack work?

An application builds a Faraday connection against a trusted base URL (e.g. http://safe.local/api) but forwards an attacker-influenced path string into get()/post(); if that path is //evil.com/..., build_exclusive_url's guard lets it through and the merged URL's authority becomes evil.com instead of safe.local, so the outbound request leaves the configured host entirely.

Which faraday versions are affected by CVE-2026-25765, and where is it fixed?

Affects faraday >= 1.0.0, <= 1.10.4 and >= 2.0.0, <= 2.14.0; fixed in 1.10.5 and 2.14.1.

How severe is CVE-2026-25765?

Medium severity, CVSS 5.8.

How can I reproduce CVE-2026-25765?

Download the verified script and run it in an isolated environment against an application using a vulnerable faraday connection with a trusted base URL; it passes a //-prefixed path into a request and confirms the outbound connection is redirected to the attacker-chosen host instead of the configured base host.
11 · References

References for CVE-2026-25765

Authoritative sources for CVE-2026-25765 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.