
Cloud Vulnerability DB
A community-led vulnerabilities database
File: lib/doorkeeper/oauth/client/credentials.rb
Line: 9-14 (Client::Credentials.from_request)
Affected component: Client authentication, used by POST /oauth/token, POST /oauth/revoke, and POST /oauth/introspect
CWE: CWE-287 — Improper Authentication
Severity: Low
CVSS: 4.0 — CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
RFC 6749 §2.3 states: "The client MUST NOT use more than one authentication
method in each request." Client::Credentials.from_request does not enforce
this:
Credentials = Struct.new(:uid, :secret) do
class << self
def from_request(request, *credentials_methods)
credentials_methods.inject(nil) do |_, method|
method = self.method(method) if method.is_a?(Symbol)
credentials = Credentials.new(*method.call(request))
break credentials if credentials.present?
end
end
...With the default client_credentials_methods of %i[from_basic from_params]
(lib/doorkeeper/config.rb:600), this walks extraction methods in order and
simply returns the first one that yields non-blank credentials — any
other credentials present in the same request are silently discarded with no
error, warning, or log entry.
POST /oauth/token (or /oauth/revoke, /oauth/introspect)
carries both an Authorization: Basic <client_A_creds> header and
client_id/client_secret form parameters for a different, unrelated
client B.Registered two confidential OAuth applications (Client A, Client B), then:
curl -u "<Client A uid>:<Client A secret>" -X POST http://localhost:3099/oauth/token \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=<Client B uid>" \
--data-urlencode "client_secret=<Client B secret>"Result: HTTP 200, access token issued. Inspecting the token server-side
confirmed token.application_id belonged to Client A (the Basic-auth
identity) — Client B's complete, valid credentials in the body were silently
discarded with no error.
def from_request(request, *credentials_methods)
credentials_methods.inject(nil) do |_, method|
method = self.method(method) if method.is_a?(Symbol)
credentials = Credentials.new(*method.call(request))
break credentials if credentials.present?
end
enddef from_request(request, *credentials_methods)
matches = credentials_methods.filter_map do |method|
method = self.method(method) if method.is_a?(Symbol)
credentials = Credentials.new(*method.call(request))
credentials if credentials.present?
end
raise Errors::DoorkeeperError, "multiple client authentication methods" if matches.size > 1
matches.first
endNote: this exact defect class was already identified and fixed by the
maintainers in the unreleased 6.0 client-authentication registry (commit
4289785e, "Reject requests using multiple client authentication methods
(RFC 6749 §2.3)"). That fix applies to the new registry-based mechanism
introduced during 6.0 development and does not cover the Client::Credentials
path used by every currently released version (including the latest stable
5.9.3), since that file does not exist on main anymore. This report
requests the equivalent fix be applied to the maintenance branch(es) serving
currently released versions.
Dynamically confirmed on v5.9.3 in a local Rails lab (spec/dummy app, Puma, Ruby 3.3.8) on 2026-08-01 — see reproduction steps above.
Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."