{"description":"Trending threats, MITRE ATT\u0026CK coverage, and detection metadata. Fed continuously.","feed_url":"https://feed.craftedsignal.io/products/oauth2--0.4.0--2.0.21/feed.json","home_page_url":"https://feed.craftedsignal.io/","items":[{"_cs_actors":[],"_cs_cpes":[],"_cs_cves":[],"_cs_exploited":false,"_cs_has_poc":false,"_cs_poc_references":[],"_cs_products":["oauth2 (\u003e= 0.4.0, \u003c= 2.0.21)"],"_cs_severities":["high"],"_cs_tags":["oauth2","ruby","vulnerability","credential-disclosure","ssrf","redirect","ghsa"],"_cs_type":"advisory","_cs_vendors":["ruby-oauth"],"content_html":"\u003cp\u003eA critical vulnerability (CVE-2026-54603) exists in the \u003ccode\u003eOAuth2::Client\u003c/code\u003e component of the \u003ccode\u003eoauth2\u003c/code\u003e Ruby gem, affecting versions from 0.4.0 up to and including 2.0.21. This flaw stems from improper resolution of protocol-relative redirect URIs within the \u003ccode\u003eOAuth2::Client#request\u003c/code\u003e method. When an OAuth2 application makes a request and its configured Identity Provider (IdP) or an open-redirect vulnerability can be influenced to return a 30x redirect with a \u003ccode\u003eLocation\u003c/code\u003e header such as \u003ccode\u003e//attacker.example/leak\u003c/code\u003e, the \u003ccode\u003eOAuth2::Client\u003c/code\u003e incorrectly merges this URI. As a result, the subsequent request, including the \u003ccode\u003eAuthorization: Bearer \u0026lt;access-token\u0026gt;\u003c/code\u003e header, is redirected to the attacker-controlled host instead of remaining with the trusted IdP. This vulnerability leads to both cross-origin credential disclosure and potential Server-Side Request Forgery (SSRF) from the application server, allowing attackers to steal sensitive tokens and probe internal networks.\u003c/p\u003e\n\u003ch2 id=\"attack-chain\"\u003eAttack Chain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eAn application, using \u003ccode\u003eOAuth2::AccessToken\u003c/code\u003e via \u003ccode\u003eOAuth2::Client\u003c/code\u003e, initiates a request to a trusted Identity Provider (IdP) or resource server, including an \u003ccode\u003eAuthorization: Bearer \u0026lt;access-token\u0026gt;\u003c/code\u003e header.\u003c/li\u003e\n\u003cli\u003eAn attacker, by exploiting an open redirect vulnerability on the IdP, configuring a malicious tenant in a multi-tenant setup, or through a network compromise, causes the IdP to issue an HTTP 30x redirect response.\u003c/li\u003e\n\u003cli\u003eThe crafted redirect response's \u003ccode\u003eLocation\u003c/code\u003e header contains a protocol-relative URI pointing to an attacker-controlled host (e.g., \u003ccode\u003e//attacker.example/leak\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eOAuth2::Client#request\u003c/code\u003e method attempts to resolve this redirect by calling \u003ccode\u003eresponse.response.env.url.merge(location)\u003c/code\u003e. Per RFC 3986 §5.2, \u003ccode\u003eURI#merge\u003c/code\u003e interprets the protocol-relative URI as a network-path reference, which overrides the authority (scheme and host) of the base URL.\u003c/li\u003e\n\u003cli\u003eThe library then recursively re-invokes \u003ccode\u003erequest(verb, full_location, req_opts)\u003c/code\u003e using the newly resolved attacker-controlled URL. Crucially, the \u003ccode\u003ereq_opts\u003c/code\u003e dictionary, containing the original request headers, is passed verbatim.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eAuthorization: Bearer \u0026lt;access-token\u0026gt;\u003c/code\u003e header, initially set by \u003ccode\u003eOAuth2::AccessToken#configure_authentication!\u003c/code\u003e, is preserved and transmitted in the request to the attacker's host.\u003c/li\u003e\n\u003cli\u003eThe attacker-controlled server receives the application's bearer token, achieving immediate cross-origin credential disclosure without further user interaction.\u003c/li\u003e\n\u003cli\u003eAlternatively, if the \u003ccode\u003eLocation\u003c/code\u003e URI specifies an internal network address (e.g., \u003ccode\u003e//169.254.169.254/\u003c/code\u003e), the application server acts as a Server-Side Request Forgery (SSRF) proxy, allowing the attacker to interact with internal resources.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"impact\"\u003eImpact\u003c/h2\u003e\n\u003cp\u003eSuccessful exploitation of this vulnerability results in two primary impacts:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eCross-origin credential disclosure:\u003c/strong\u003e The immediate consequence is the theft of \u003ccode\u003eAuthorization: Bearer\u003c/code\u003e tokens. Any application utilizing the vulnerable \u003ccode\u003eoauth2\u003c/code\u003e gem to communicate with an IdP susceptible to such redirection risks having its access tokens exfiltrated to an attacker-controlled server. This can lead to unauthorized access to user data or resources that the stolen token grants access to.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eServer-Side Request Forgery (SSRF):\u003c/strong\u003e The ability to redirect the application's requests to an arbitrary host also enables SSRF. Attackers can leverage this to force the application server to make requests to internal network services, cloud metadata endpoints (e.g., \u003ccode\u003e169.254.169.254\u003c/code\u003e), or other restricted resources that are typically inaccessible from the internet. This could facilitate reconnaissance, lateral movement, or further exploitation within an organization's internal infrastructure. Given the widespread use of OAuth2 in modern applications, the potential number of affected services and organizations is substantial across all sectors.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"recommendation\"\u003eRecommendation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpgrade the \u003ccode\u003eoauth2\u003c/code\u003e gem to version \u003ccode\u003e2.0.22\u003c/code\u003e or later immediately to address CVE-2026-54603.\u003c/li\u003e\n\u003cli\u003eApply the suggested patch logic to \u003ccode\u003eOAuth2::Client#request\u003c/code\u003e as an interim measure if immediate gem upgrade is not possible. This involves forcing protocol-relative \u003ccode\u003eLocation\u003c/code\u003e values to be interpreted as relative paths by prepending \u003ccode\u003e./\u003c/code\u003e before \u003ccode\u003eURI#merge\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eDevelopers should review their Identity Provider (IdP) and resource server configurations to ensure they do not expose open redirect vulnerabilities that could be abused to supply malicious \u003ccode\u003eLocation\u003c/code\u003e headers.\u003c/li\u003e\n\u003cli\u003eImplement defense-in-depth measures to strip credential-bearing headers (like \u003ccode\u003eAuthorization\u003c/code\u003e) from requests when a redirect crosses origin boundaries, similar to how robust HTTP clients handle such scenarios.\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-07-28T16:33:59Z","date_published":"2026-07-28T16:33:59Z","id":"https://feed.craftedsignal.io/briefs/2026-07-oauth2-client-redirect-leak/","summary":"The `OAuth2::Client` in the `oauth2` Ruby gem is vulnerable to credential disclosure and Server-Side Request Forgery (SSRF) due to improper handling of protocol-relative redirect URLs, allowing an attacker to steal bearer tokens and access internal network resources.","title":"OAuth2::Client Redirection Vulnerability Leaks Bearer Tokens","url":"https://feed.craftedsignal.io/briefs/2026-07-oauth2-client-redirect-leak/"}],"language":"en","title":"CraftedSignal Threat Feed - Oauth2 (\u003e= 0.4.0, \u003c= 2.0.21)","version":"https://jsonfeed.org/version/1.1"}