CVE-2026-94386
Camel-OAuth: Cross-scope token reuse via an under-keyed JVM-global client credentials token cache
Description
OAuthClientCredentialsTokenResolver obtains OAuth 2.0 bearer tokens through the client credentials grant on behalf of the components that authenticate their outbound calls with a named OAuth profile, such as camel-openai, camel-langchain4j-agent, camel-huggingface, camel-docling, camel-a2a, camel-spring-ai-chat and the IBM watsonx components, and of applications that call the OAuthClientAuthenticationFactory SPI directly. It kept the tokens it obtained in a static cache shared by every resolver instance and every CamelContext in the JVM, and keyed that cache on the token endpoint and the client ID only, although the token request also carries the client secret and the requested scope. Two profiles that share a token endpoint and a client ID but request different scopes, or authenticate with different client secrets, therefore mapped to the same cache entry: the profile that resolved a token first populated the entry, and the other profile was then handed that token, with no token request made under its own configuration, for as long as the token remained valid. Token caching is enabled by default, and pointing several profiles at one identity provider client is an ordinary use of the profile support rather than an opt-in to an insecure setting. The outcome is an outbound request that carries a token issued for another profile's scope, which can grant broader authority than the calling profile was configured for, or reach a service the token was not issued for; with identity providers that derive a token's audience from the requested scope, a different scope can mean a token for a different service altogether. A profile configured with a different client secret was likewise served the token obtained with the other secret, without authenticating with its own. The profiles are configured by the deployment, which is trusted, so no untrusted input reaches the cache: the party that gains is the service that receives a token it was not meant to receive, which, if hostile or compromised, can replay that token within its scope. Reaching the issue requires a deployment that defines more than one profile sharing a token endpoint and client ID while differing in scope or client secret.
Mitigation
Credit
This issue was discovered by Andrea Cosentino from Apache Software Foundation
Notes
The JIRA ticket: https://issues.apache.org/jira/browse/CAMEL-24872 refers to the commits that resolved the issue, and has more details.
The fix was merged on main in https://github.com/apache/camel/pull/26681 (commit 5e896b2df24bf80ad4a78be1f8a708f71d91aa16), and backported to camel-4.22.x in https://github.com/apache/camel/pull/27779 (commit b2d9957bcbcf87bd5e59992fec45231876c645ed).
The cache key now holds every input of the token request: the token endpoint, the client ID, a SHA-256 fingerprint of the client secret, so that the raw secret is not kept in the static cache, and the requested scope. An absent, empty or blank scope counts as one value, because each of them leaves the scope parameter out of the request; any other scope is matched exactly. Profiles that agree on all four still share a token across resolver instances, while profiles that differ in credentials or scope obtain separate tokens. The cache-tokens option and its default are unchanged, and setting it to false still requests a fresh token on every resolution. As the upgrade guide notes, applications that define such profiles may make additional token requests after upgrading.
The client credentials token resolver and its cache were added in 4.19.0 by https://issues.apache.org/jira/browse/CAMEL-23093, which let other components obtain bearer tokens through camel-oauth with a named profile, and the cache was keyed on the token endpoint and client ID from the start, so the affected range begins at that release. The 4.18.x line and earlier do not contain the resolver and are not affected, although camel-oauth itself is older.
This is the same class of defect as CVE-2026-85317, in which the OAuth2 client token cache of camel-http was keyed on fewer fields than shape the token. The two caches are separate code and that fix did not touch camel-oauth; here, unlike in camel-http, token caching is enabled by default, and the key also left out the client secret. The issue is also distinct from CVE-2026-80312 and CVE-2026-84178, which concerned the inbound processors of camel-oauth: 4.22.1, which fixes those two, is still affected by this one. It is classified as CWE-524 (Use of Cache Containing Sensitive Information).