Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
💎
💎 RubyGems
Not in CISA KEV
HIGH severity

GHSA-prq8-7wvh-44qh

HIGHFix: ruby-oauth/oauth@d069dc8

GHSA-prq8-7wvh-44qh is a high-severity (CVSS 7.2) Information Exposure vulnerability in oauth. O3 Security confirms whether GHSA-prq8-7wvh-44qh is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

OAuth: Cross-origin token-request redirects can expose signed request metadata

Also known asCVE-2026-54605
Published
Jul 28, 2026
Updated
Jul 28, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 11, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for GHSA-prq8-7wvh-44qh.

EPSS Exploitation Probability

via FIRST.org ↗
0.1%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs3th percentile — riskier than 3% of all scored CVEsHighest risk
0.00%0.21%0.42%0.63%0.1%0.1%0.1%Aug 26Sep 26Sep 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-prq8-7wvh-44qh plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 0 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
💎oauth

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects RubyGems packages — download data is not available via public APIs for these ecosystems.

Description

Cross-origin OAuth token-request redirects can expose signed request metadata

Summary

When an application uses OAuth::Consumer to request OAuth 1.0 request tokens or access tokens, the token request helper follows 300..399 redirects returned by the OAuth server. In affected versions, OAuth::Consumer#token_request parses the raw Location header, follows the redirect recursively, and can mutate the consumer's configured site when the redirect points to a different host with the same path.

The result is a cross-origin signed-request disclosure primitive: if an OAuth server token endpoint returns a redirect whose target an attacker controls, the client can re-sign the token request and send OAuth 1.0 request metadata, including the OAuth signature, nonce, timestamp, consumer key, and any request parameters included in the signature base string, to the attacker-controlled host. The same behavior can also be used as an SSRF or confused-deputy primitive because the application server follows the redirect and sends the next request from its own network position.

Affected

  • oauth v1.1.5 and prior versions back to and including v0.5.5.
  • The vulnerable behavior is in OAuth::Consumer#token_request, which is used by the documented request-token and access-token flows.
  • The issue is not specific to a Ruby engine or platform. It is caused by the gem's redirect handling and recursive token request behavior.

Patched version: oauth v1.1.6.

Impact

A consumer that calls OAuth::Consumer#get_request_token, OAuth::Consumer#get_access_token, or lower-level token request helpers against an OAuth server whose token endpoint redirect target can be influenced may lose three security properties:

  1. Cross-origin signed-request metadata disclosure. The redirected request is signed for the attacker-controlled endpoint. Depending on the request method, scheme, and parameters, the attacker may receive OAuth 1.0 parameters such as oauth_consumer_key, oauth_signature_method, oauth_timestamp, oauth_nonce, oauth_version, and oauth_signature.
  2. SSRF from the application server. The OAuth client follows the redirect on behalf of the application, so the redirected host is contacted from the application server's network position.
  3. Confused-deputy behavior. A malicious or compromised token endpoint can cause an otherwise trusted application to initiate signed requests to an unintended origin.

The disclosed OAuth 1 signature is not equivalent to an OAuth 2 bearer token: it is bound to the signed request, timestamp, nonce, HTTP method, and request URL. However, it can still disclose sensitive integration metadata, may be replayable within the receiver's accepted nonce/timestamp window in some deployments, and can expose application-server reachability to attacker-selected hosts.

Vulnerable code

lib/oauth/consumer.rb at tag v1.1.5:

def token_request(http_method, path, token = nil, request_options = {}, *arguments)
  request_options[:token_request] ||= true
  response = request(http_method, path, token, request_options, *arguments)
  case response.code.to_i

  when (200..299)
    # parse token response
  when (300..399)
    # Parse redirect to follow
    uri = URI.parse(response["location"])
    our_uri = URI.parse(site)

    # Guard against infinite redirects
    response.error! if uri.path == path && our_uri.host == uri.host

    if uri.path == path && our_uri.host != uri.host
      options[:site] = "#{uri.scheme}://#{uri.host}"
      @http = create_http
    end

    token_request(http_method, uri.path, token, request_options, arguments)
  when (400..499)
    raise OAuth::Unauthorized, response
  else
    response.error!
  end
end

The vulnerable behavior has several parts:

  • response["location"] is trusted as the next token request target.
  • Redirects are followed for every 300..399 response.
  • There is no general redirect counter or maximum redirect limit.
  • Cross-host redirects with the same path can mutate options[:site] and rebuild the underlying HTTP client.
  • The recursive call continues the token request flow and signs the next request for the redirected destination.

Reachable in production

The vulnerable path is reachable through the normal OAuth 1 token exchange:

consumer = OAuth::Consumer.new(
  consumer_key,
  consumer_secret,
  site: "https://provider.example"
)

request_token = consumer.get_request_token

If https://provider.example/oauth/request_token returns a redirect to an attacker-controlled host, the library follows that redirect as part of the token request flow. A realistic trigger is an OAuth provider, gateway, or reverse proxy that emits Location based on user-controlled or tenant-controlled input, or a malicious tenant-controlled OAuth endpoint in a multi-tenant integration.

No application-level redirect handling is required. The redirect is followed inside the gem before the application receives the token response.

Reproduction

A vulnerable application is one that uses OAuth::Consumer to perform an OAuth 1 token exchange against a token endpoint that can be made to return a redirect to another origin.

Example shape:

consumer = OAuth::Consumer.new(
  consumer_key,
  consumer_secret,
  site: "https://provider.example"
)

consumer.get_request_token

If https://provider.example/oauth/request_token responds with a 30x redirect whose Location points to https://attacker.example/..., affected versions may follow that redirect as part of the token request flow. The redirected request is then generated and signed by the application server for the new destination. Depending on the configured OAuth request scheme, OAuth 1 parameters may be sent in the Authorization header, request body, or query string.

Expected vulnerable behavior:

  • the token request leaves the configured OAuth provider origin;
  • the redirected host receives a signed OAuth 1 token request;
  • the application does not get a chance to inspect or approve the redirect target before the redirected request is sent.

Expected patched behavior:

  • same-origin redirects continue to work, subject to a redirect limit;
  • cross-origin token endpoint redirects are rejected by default;
  • applications that intentionally require cross-origin token redirects must opt in explicitly with token_request_cross_origin_redirects.

Suggested fix

Reject cross-origin token endpoint redirects by default and require explicit opt-in for integrations that intentionally depend on that behavior.

The fix released in v1.1.6 does the following:

current_uri = token_request_uri(path)
redirected_uri = token_request_redirect_uri(current_uri, response)
response.error! unless redirected_uri

redirect_count = request_options[:token_request_redirect_count].to_i + 1
response.error! if redirect_count > token_request_max_redirects(request_options)
response.error! if token_request_cross_origin?(current_uri, redirected_uri) &&
  !token_request_cross_origin_redirects?(request_options)

redirect_options = request_options.merge(token_request_redirect_count: redirect_count)
token_request(http_method, token_request_redirect_path(current_uri, redirected_uri), token, redirect_options, *arguments, &block)

The fix intentionally preserves same-origin redirect compatibility while making cross-origin token endpoint redirects an explicit choice. It also avoids placing internal redirect state in request_options passed to OAuth signing.

Workarounds

Until a patched release is available, applications can reduce exposure by doing one or more of the following:

  • Ensure configured OAuth token endpoints are fixed absolute URLs controlled by a trusted provider.
  • Do not use tenant-controlled OAuth token endpoint URLs unless the tenant is trusted to receive signed OAuth token requests.
  • Block outbound application-server traffic to internal metadata services and other sensitive internal addresses at the network layer.
  • Place a trusted proxy in front of OAuth providers that rejects token endpoint redirects to a different origin.

These mitigations reduce exploitability but do not remove the vulnerable redirect logic from the gem.

Credit

Found during the follow-up audit for GHSA-pp92-crg2-gfv9.

Reporter/coordinator: Peter H. Boling (pboling).

References

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
💎RubyGemsoauth0.5.5&&< 1.1.61.1.6

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for oauth. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update oauth to 1.1.6 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-prq8-7wvh-44qh is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-prq8-7wvh-44qh is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-prq8-7wvh-44qh. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

# Cross-origin OAuth token-request redirects can expose signed request metadata ## Summary When an application uses `OAuth::Consumer` to request OAuth 1.0 request tokens or access tokens, the token request helper follows `300..399` redirects returned by the OAuth server. In affected versions, `OAuth::Consumer#token_request` parses the raw `Location` header, follows the redirect recursively, and can mutate the consumer's configured `site` when the redirect points to a different host with the same path. The result is a cross-origin signed-request disclosure primitive: if an OAuth server token
O3 Security · Impact-Aware SCA

Is GHSA-prq8-7wvh-44qh in your dependencies?

O3 detects GHSA-prq8-7wvh-44qh across RubyGems dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.

GHSA-prq8-7wvh-44qh: oauth SSRF (High 7.2) | O3 Security