Skip to main content
Vulnerability Database/CVE-2026-82755

CVE-2026-82755: OAuth2 Server Cache Information Disclosure

CVE-2026-82755 is a cache poisoning flaw in ash_authentication_oauth2_server that causes shared HTTP caches to serve OAuth metadata from one tenant to another. This post covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-82755 Overview

CVE-2026-82755 is an information disclosure vulnerability in the ash-project/ash_authentication_oauth2_server library for Elixir. The flaw resides in AshAuthentication.Phoenix.Oauth2Server.ProtocolRouter, which serves RFC 8414 and RFC 9728 OAuth discovery metadata endpoints. The router returns tenant-specific values such as issuer, authorization_endpoint, token_endpoint, and jwks_uri while emitting Cache-Control: public, max-age=3600 without a Vary header. When a shared HTTP cache fronts the application and tenants are resolved from a header or Host, the cache key collapses to the URL alone, causing one tenant's metadata to be served to another tenant's clients for up to an hour. Versions 0.1.3 through 0.3.0 are affected [CWE-524].

Critical Impact

Affected OAuth clients may deliver authorization codes and client secrets to the wrong tenant's token endpoint and validate issued tokens against the wrong jwks_uri keys.

Affected Products

  • ash_authentication_oauth2_server versions >= 0.1.3, < 0.3.1
  • Elixir/Phoenix applications using AshAuthentication.Phoenix.Oauth2Server.ProtocolRouter
  • Multi-tenant deployments behind shared HTTP caches, CDNs, or reverse proxies

Discovery Timeline

  • 2026-09-07 - CVE-2026-82755 published to NVD
  • 2026-09-08 - Last updated in NVD database

Technical Details for CVE-2026-82755

Vulnerability Analysis

The OAuth 2.0 Authorization Server Metadata (RFC 8414) and Protected Resource Metadata (RFC 9728) endpoints expose per-tenant endpoint URLs and key material references. ProtocolRouter computes those values from the current tenant context, then serializes the response with a permissive public caching directive. Because the response varies by tenant but the HTTP request does not include a discriminating header in Vary, any intermediary that honors Cache-Control: public treats responses as interchangeable across tenants sharing the same path.

Downstream OAuth clients rely on these documents to locate the token endpoint and fetch signing keys. If a cached document from tenant A is served to a client acting for tenant B, that client will submit authorization codes and client credentials to tenant A's token_endpoint and validate returned tokens against tenant A's jwks_uri. This crosses trust boundaries between tenants and can expose credentials to the wrong operator.

Root Cause

The root cause is a mismatch between the response's variability and its cache key. Tenant resolution happens outside the URL, from a header or the Host value, but the response advertises public, max-age=3600 with no Vary directive to signal that variability to caches. Shared caches therefore key only on the URL and reuse tenant A's response for tenant B [CWE-524].

Attack Vector

An attacker or benign client whose request populates a shared cache first can cause that cached metadata to be returned to other tenants' clients for the cache's freshness window. Exploitation does not require authentication. It requires that a shared cache sits between clients and the application and that tenants are not disambiguated in the URL.

text
     conn
     |> put_resp_header("content-type", "application/json")
-    |> put_resp_header("cache-control", "public, max-age=3600")
+    |> put_resp_header("cache-control", metadata_cache_control(conn))
     |> send_resp(200, Jason.encode!(Metadata.protected_resource(server, secret_context(conn))))
     |> halt()
   end

Source: GitHub Commit 768d87f - the patch replaces the static public, max-age=3600 header with a context-aware metadata_cache_control/1 helper that avoids shared-cache storage for tenant-specific responses.

Detection Methods for CVE-2026-82755

Indicators of Compromise

  • Cached responses for /.well-known/oauth-authorization-server or /.well-known/oauth-protected-resource containing an issuer or endpoint URL that does not match the requesting tenant.
  • OAuth client logs showing token requests sent to a token_endpoint belonging to a different tenant than the one the client was configured for.
  • JWT validation failures where the iss claim or signing key origin does not correspond to the expected tenant.

Detection Strategies

  • Inventory deployments of ash_authentication_oauth2_server and flag any version at or above 0.1.3 and below 0.3.1.
  • Inspect responses from the RFC 8414 and RFC 9728 discovery endpoints for Cache-Control: public without a corresponding Vary header covering the tenant selector.
  • Correlate CDN or reverse-proxy access logs with tenant identifiers to detect cross-tenant reuse of cached metadata documents.

Monitoring Recommendations

  • Alert on OAuth token exchanges where the target token_endpoint host or path does not match the requesting tenant's expected configuration.
  • Monitor for JWKS fetches that resolve to unexpected jwks_uri values across tenants.
  • Track HTTP cache hit ratios on /.well-known/* OAuth endpoints and investigate anomalous hit rates that suggest cross-tenant reuse.

How to Mitigate CVE-2026-82755

Immediate Actions Required

  • Upgrade ash_authentication_oauth2_server to version 0.3.1 or later.
  • Purge shared cache entries for /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource after upgrade.
  • Audit tenants whose clients may have transmitted authorization codes or secrets to the wrong token_endpoint and rotate any exposed client secrets.

Patch Information

The fix is delivered in commit 768d87f70e4e97ae1d2bf1606b5bf3f4d03f24a1 and released in version 0.3.1. See the GitHub Security Advisory GHSA-crqf-7m54-4hgc and the CNA CVE-2026-82755 Entry for full details.

Workarounds

  • Configure the shared cache or CDN to bypass caching for OAuth discovery endpoints until the patched version is deployed.
  • Override the response with Cache-Control: private or no-store at a reverse proxy in front of the Phoenix application.
  • Move tenant selection into the URL path so that shared caches key responses per tenant and cannot cross tenant boundaries.
bash
# NGINX example: disable shared caching for OAuth discovery endpoints
location ~ ^/\.well-known/(oauth-authorization-server|oauth-protected-resource)$ {
    proxy_pass http://phoenix_upstream;
    proxy_hide_header Cache-Control;
    add_header Cache-Control "private, no-store" always;
    proxy_cache_bypass 1;
    proxy_no_cache 1;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.