PHP2Shell: Read our blog on the critical RCE vulnerabilities affecting 70% of the Internet
Vulnerability DatabaseGHSA-c62j-746x-gfcr

GHSA-c62j-746x-gfcr: 
Ruby vulnerability analysis and mitigation

Impact

Doorkeeper accepts an access token through three transmission methods — the Authorization: Bearer header, a form-encoded body parameter, and a URI query parameter (access_token / bearer_token) — as configured by access_token_methods. RFC 6750 §2 requires that a client "MUST NOT use more than one method to transmit the token in each request", and §3.1 requires a resource server to answer such a request with invalid_request. Doorkeeper instead authorized the request with the first configured method that yielded a token and silently discarded every other token presented in the same request. Which token authorizes the request was therefore decided by the server's configured method order, not by what the caller sent, and the form-encoded body and the URI query were never told apart at all, because both Rails and Rack merge them into a single parameter hash before Doorkeeper reads it (Rails lets the query win, Rack lets the body win). This affects every resource protected with doorkeeper_authorize! (Rails and Grape, and controllers built on Doorkeeper's own base classes), GET /oauth/token/info, and the bearer-token authorization path of POST /oauth/introspect. Two consequences:

  1. Confused deputy. A gateway or service mesh that attaches its own Authorization: Bearer while forwarding a caller-controlled access_token parameter runs the request under the gateway's identity; the caller's token is discarded without any error or log entry. Attribution, rate limiting and resource_owner_id resolution are then wrong.
  2. Layer desync. A WAF, gateway or custom middleware that inspects one transmission method while Doorkeeper authorizes on another reaches a different verdict about the same request: a request that passed a scope check on one token executes under another. No privilege beyond holding the presented tokens is needed, and the impact depends on a proxy/gateway topology in front of Doorkeeper, which is why the severity is Medium.

Details

Measured on v5.9.6 with two access tokens for two different applications and two different resource owners, default access_token_methods:

RequestResult
Authorization: Bearer <A> + ?access_token=<B>200 — served under A, B discarded
?access_token=<A>&bearer_token=<B>200 — served under A, B discarded
Authorization: Bearer <revoked B> + ?access_token=<valid A>401 — the valid token is discarded
same request as row 1 with access_token_methods order reversed403 — now the parameter wins
POST with access_token=<A> in the body and ?access_token=<B> in the query200 — served under B on Rails, under A on Grape

Patches

The fix counts how many transmission methods carry a token and refuses the request when there is more than one. Only the built-in extraction methods take part in the check; a custom callable configured in access_token_methods keeps the historical first-wins behaviour, mirroring the exemption client authentication gives its legacy callable extractors.

  • 6.0.0 refuses such a request with the invalid_request (HTTP 400) response RFC 6750 §3.1 prescribes, at every affected surface. The body and the query count as two methods, and the same token repeated across two methods is refused as well. Doorkeeper.authenticate and the doorkeeper_token helpers keep their token-or-nil contract; under handle_auth_errors :raise the request raises Doorkeeper::Errors::InvalidRequest (a sibling of Doorkeeper::Errors::InvalidToken, not a subclass). A new doorkeeper_bad_request_render_options controller hook customizes the 400 body. See the 6.0.0 CHANGELOG and upgrade guide.
  • 5.9.7 fails closed instead: a request that transmits different tokens by more than one method is treated as carrying no usable token and answered invalid_token (HTTP 401), with no change to any public method's contract. The stricter invalid_request answer is 6.0-only.

Workarounds

If you cannot upgrade, reduce access_token_methods to a single method (for example access_token_methods :from_bearer_authorization) so that only one transmission method is read, and make any gateway, WAF or middleware in front of Doorkeeper read the same one. Note that this does not detect the body/query collision for the parameter methods; only upgrading does.

References

  • RFC 6750 §2 (transmission methods), §2.2 / §2.3 (form body and URI query), §3.1 (invalid_request)
  • GHSA-c8r6-23w7-5q9p — the same first-wins shape on the client authentication side (RFC 6749 §2.3)

Source: NVD

Related Ruby vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-9h43-g84r-c93mHIGH7.4
  • Ruby logoRuby
  • doorkeeper-openid_connect
NoYesOct 21, 2026
GHSA-wgw9-qhqg-8hv5MEDIUM5.3
  • Ruby logoRuby
  • sanitize
NoYesOct 21, 2026
GHSA-pq4g-8rxf-4g29MEDIUM5.3
  • Ruby logoRuby
  • crass
NoYesOct 21, 2026
GHSA-c62j-746x-gfcrMEDIUM4.8
  • Ruby logoRuby
  • doorkeeper
NoYesOct 21, 2026
GHSA-c8r6-23w7-5q9pLOWN/A
  • Ruby logoRuby
  • doorkeeper
NoNoOct 21, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management