Neo found a Server-Side Request Forgery (SSRF) vulnerability in Faraday, a widely used HTTP client library in the Ruby ecosystem. This is Neo’s first credited CVE discovery.
Neo is ProjectDiscovery’s AI security copilot for tasks like code review and vulnerability discovery. For this finding, Neo reviewed a widely used open source dependency and, without human guidance, surfaced a subtle URL-handling edge case, validated it in runtime, and produced a clear write-up that maintainers could patch.
Takeaway: Neo accomplished the type of deep review that can take senior engineers hours to complete. When you apply the same workflow for code review, Neo can save security teams significant time while catching critical security risks before they hit production.
//evil.com, overriding the destination host inside build_exclusive_urlCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:NFaraday is one of the most common HTTP client libraries in the Ruby ecosystem, so it sits in the critical path of how Ruby applications make outbound requests. Faraday is also widely used, with 5.9k GitHub stars, 1.1 billion downloads, and packaged as part of applications including GitLab, Fastlane, and Google Auth.
SSRF, or Server-Side Request Forgery, is when an attacker can steer where your server sends an outbound request by supplying input that looks harmless, but changes the real destination.
Scanners often miss SSRF because it is usually a logic and URL parsing edge case, not a single “dangerous function.” For example, code may try to lock requests to a trusted base URL, but an input like //evil.com/path can be treated by URL libraries as “use this host,” not “use this path.” To confirm SSRF, you have to trace the input to the final request destination and verify where the server actually goes. These issues often slip past scanners and only get discovered during deep review by engineers.
Neo began reviewing Faraday’s code like a human
Neo did not start the way most scanners do, by pattern matching for obviously risky calls like eval or exec. Those checks are useful for catching common classes of bugs, but they are not how a human reviewer finds the more obscure issues that hide in normal, safe-looking code.
Instead, Neo mapped the full codebase and then narrowed its attention to the handful of files that control URL building and request routing. In Faraday, that meant starting with connection.rb and the URL and request helpers, because that is where a trusted base URL and a caller-provided path turn into a real outbound request.
That approach matters because subtle vulnerabilities tend to appear when two pieces of correct behavior interact in an unexpected way as we’ll see below.

Tracing the URL logic and showing the bypass
Once Neo built a map of the repo, it looked for the choke point where Faraday turns two inputs into a destination: a trusted base URL and a caller-provided path. That trail led to build_exclusive_url in connection.rb, because it is the function responsible for combining those values into the final request URL.

Inside that method, Neo found what looks like a reasonable safety check: Faraday prevents callers from overriding the base URL with a full absolute URL by checking how the input starts. If the input looks like an absolute URL, it is treated differently. If it looks like a normal path, it is allowed.
However, the check intentionally allows inputs that start with /, because apps need to pass paths like /api/v1/users. But there is a special kind of URL that also starts with / and is easy to miss if you are not thinking about how URL libraries interpret it: a URL that starts with two slashes, like //evil.com/steal.
Neo recognized that this form is not “just a path.” Under the rules browsers and URL libraries follow, //evil.com/steal is treated as “use this host,” while inheriting the scheme from the base URL. So when Faraday merges:
https://api.internal.com//evil.com/stealthe result can become:
https://evil.com/stealIn other words, a value that passes a “starts with /” allowlist can still change the destination host.
A minimal trigger looks like this:
If an attacker can influence that path value, they can redirect where the server sends requests. That is SSRF.
From finding to fix

Neo did not stop at “this looks suspicious.” It documented the issue in a way a human could act on, including the exact code path, a minimal reproducer, the conditions required for impact, and a clear remediation direction. That matters because the hard part of security review is turning findings into something reproducible that can be patched. With this report, the maintainers were able to confirm the behavior and ship a fix, which became CVE-2026-25765.
To see if whether traditional scanners would have caught this, we ran the Faraday repo through Snyk SAST and Semgrep.
Snyk did not surface any issues for this snapshot.

Semgrep did return findings, but they were unrelated to URL construction. The results we saw were low-severity shell hygiene findings in scripts, which is expected. Tools like Snyk and Semgrep are strongest at repeatable pattern coverage, while this issue lives in safe-looking logic and an edge case most rulesets do not model.

This is not a knock on Snyk nor Semgrep. Scanners like these are designed to catch broad classes of known issues using consistent rules, but some vulnerabilities do not look like “bad code” in isolation. They hide in safe-looking logic and only show up when you reason through edge cases and how the pieces behave together. That is the gap Neo is built to fill: it can do that reviewer-style reasoning autonomously, then hand you a concrete, reproducible finding instead of a generic alert.
Security issues often hide in edge cases. They live in code that looks reasonable and passes review because the failure is an assumption that breaks when normal pieces interact, like URL handling rules plus a guardrail meant to keep requests safe.
Traditional scanners are valuable for broad, consistent coverage, but they rarely catch these behavior gaps reliably. Historically, teams have covered that gap with senior manual review, pentests, and bug bounty research, but those solutions are expensive and hard to apply everywhere without slowing development.
The Faraday SSRF is a good example. Neo traced the code path that determines where requests go, identified an edge case that changes the destination, validated it in runtime, and documented it with a minimal repro and fix direction that maintainers could confirm and patch.
If this kind of bug can survive in a mature dependency, it can exist in internal URL and request-handling code too, and the work to catch it does not need to be purely manual anymore. Tools that can reason through code and return reproducible evidence move this class of review earlier, when fixes are cheaper, faster, and less disruptive.
Want Neo to run this kind of review on your code and dependencies? Request a demo