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

CVE-2026-82756: Ash Authentication OAuth2 Auth Bypass Flaw

CVE-2026-82756 is an authentication bypass vulnerability in ash_authentication_oauth2_server allowing attackers to inject authentication parameters into WWW-Authenticate headers. This article covers technical details, affected versions, impact analysis, and mitigation strategies.

Published:

CVE-2026-82756 Overview

CVE-2026-82756 is an output encoding vulnerability [CWE-116] in the ash_authentication_oauth2_server library for the Elixir Ash framework. The BearerPlug and RequireScopePlug modules build the WWW-Authenticate: Bearer resource_metadata="..." challenge header by interpolating a tenant-derived URL directly into the quoted value without escaping. In multi-tenant applications that derive the Ash tenant from request-controlled data such as a subdomain, Host header, path segment, or custom header, an unauthenticated attacker can inject a double-quote character to close the quoted string and append arbitrary authentication parameters. Affected versions span from 0.1.3 before 0.3.1.

Critical Impact

Attackers can inject a second resource_metadata URL pointing at an attacker-controlled authorization server, which spec-following OAuth 2.0 clients will follow during the discovery phase.

Affected Products

  • ash_authentication_oauth2_server versions 0.1.3 through 0.3.0
  • Elixir/Phoenix applications using BearerPlug for bearer token validation
  • Elixir/Phoenix applications using RequireScopePlug for scope enforcement

Discovery Timeline

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

Technical Details for CVE-2026-82756

Vulnerability Analysis

The vulnerability is a parameter injection flaw within a single HTTP response header. BearerPlug and RequireScopePlug construct the WWW-Authenticate challenge using Elixir string interpolation, embedding the resource_metadata URL directly inside the quoted auth-param value. Because the URL is derived from the request tenant via Ash.PlugHelpers.get_tenant(conn), a tenant string containing a " character terminates the quoted value early and permits attacker-controlled auth-params to be appended.

Plug rejects carriage return and line feed characters in headers, so this is not classical HTTP response splitting. The injection is confined to the WWW-Authenticate header value but is sufficient to insert a second resource_metadata parameter. RFC-compliant OAuth 2.0 clients consuming the challenge may then fetch resource metadata from the attacker's authorization server, enabling downstream identity confusion attacks.

Root Cause

The root cause is missing output encoding of tenant-derived data placed inside an RFC 7235 quoted-string. The pre-patch code used the sigil ~s|Bearer resource_metadata="#{metadata_url}"...| without escaping embedded quotes or backslashes.

Attack Vector

An unauthenticated attacker submits a request whose tenant-controlling input (subdomain, Host header, path segment, or custom header) contains a crafted string with an embedded ". When the server responds with 401 Unauthorized, the emitted WWW-Authenticate header contains attacker-injected auth-params, including a rogue resource_metadata URL.

elixir
# Pre-patch vulnerable construction (lib/ash_authentication_phoenix/oauth2_server/bearer_plug.ex)
defp challenge(conn, server, reason, scope) do
  metadata_url = Errors.resource_metadata_url(server, Ash.PlugHelpers.get_tenant(conn))

  scope_param = if scope, do: ~s|, scope="#{scope}"|, else: ""

  error_param =
    case reason do
      nil -> ""
      :invalid_audience -> ~s|, error="invalid_token", error_description="audience mismatch"|
      :invalid_issuer   -> ~s|, error="invalid_token", error_description="issuer mismatch"|
      :expired          -> ~s|, error="invalid_token", error_description="token expired"|
      _                 -> ~s|, error="invalid_token"|
    end

  conn
  |> put_resp_header(
    "www-authenticate",
    ~s|Bearer resource_metadata="#{metadata_url}"#{scope_param}#{error_param}|
  )
  |> send_resp(401, "")
end

Source: GitHub Commit 09f9747

Detection Methods for CVE-2026-82756

Indicators of Compromise

  • Outbound WWW-Authenticate response headers containing more than one resource_metadata= parameter for a single Bearer challenge.
  • Inbound requests where tenant-carrying inputs (subdomains, Host headers, or path segments) contain literal " characters or URL-encoded %22 sequences.
  • Unexpected client requests to unfamiliar authorization server metadata endpoints originating from OAuth 2.0 clients of the affected application.

Detection Strategies

  • Inspect application logs and reverse-proxy access logs for HTTP 401 responses whose WWW-Authenticate values contain unbalanced quotes or duplicate auth-param keys.
  • Add unit and integration tests that assert WWW-Authenticate values produced by BearerPlug contain exactly one resource_metadata parameter under adversarial tenant inputs.
  • Instrument the Ash.PlugHelpers.get_tenant/1 code path to log tenant values that contain characters outside the expected identifier grammar.

Monitoring Recommendations

  • Monitor egress connections from OAuth 2.0 client applications to domains not on the approved authorization server allowlist.
  • Track anomalies in 401 response rates and header lengths in the affected Phoenix endpoints.
  • Correlate suspicious tenant strings with subsequent authentication or authorization events across the Singularity Data Lake using OCSF-normalized HTTP telemetry.

How to Mitigate CVE-2026-82756

Immediate Actions Required

  • Upgrade ash_authentication_oauth2_server to version 0.3.1 or later, which introduces the centralized bearer_challenge/1 builder that RFC 7235-escapes every auth-param value.
  • Audit multi-tenant configurations to confirm how the Ash tenant is derived from request data and restrict tenant identifiers to a safe character set.
  • Review recent 401 response logs for signs of injected resource_metadata values.

Patch Information

The fix is delivered in commit 09f9747 and shipped in release 0.3.1. It replaces inline string interpolation in BearerPlug and errors.ex with a shared Errors.bearer_challenge/1 function that constructs the header from ordered {key, value} tuples, drops nil values, and escapes each value as an RFC 7235 quoted-string. See the GitHub Security Advisory GHSA-2h3v-83jg-2qmm and the CNA CVE-2026-82756 Entry for full advisory details.

Workarounds

  • Validate and normalize tenant identifiers at the plug pipeline entry point, rejecting any value containing ", \, control characters, or other characters outside [A-Za-z0-9._-].
  • Wrap BearerPlug and RequireScopePlug with a custom plug that rewrites the outbound WWW-Authenticate header using a safe, escaped builder until the upgrade is completed.
  • Constrain tenant sources to server-trusted data such as authenticated session claims rather than raw Host headers or subdomains where feasible.
bash
# Update the dependency in mix.exs and refresh the lockfile
# mix.exs
#   {:ash_authentication_oauth2_server, "~> 0.3.1"}

mix deps.update ash_authentication_oauth2_server
mix deps.get
mix compile --force

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.