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

CVE-2026-66883: Erlang oidcc_plug Auth Bypass Vulnerability

CVE-2026-66883 is an authentication bypass flaw in Erlang Ecosystem Foundation oidcc_plug that breaks user agent session binding due to case sensitivity issues. This article covers technical details, affected versions, and fixes.

Published:

CVE-2026-66883 Overview

CVE-2026-66883 affects the oidcc_plug library maintained by the Erlang Ecosystem Foundation, specifically the Oidcc.Plug.Authorize module. The vulnerability stems from improper handling of case sensitivity [CWE-178] in HTTP header lookups. The Oidcc.Plug.Authorize.call/2 function requests the User-Agent header using mixed case, while the underlying Plug library normalizes header names to lowercase. This mismatch causes the user agent lookup to always return an empty list, silently disabling the user agent session binding check even when deployments explicitly enable check_useragent: true.

Critical Impact

The user agent binding check fails open silently with no error or log entry, removing a defense-in-depth control against replay of stolen OpenID Connect sessions.

Affected Products

  • oidcc_plug versions 0.1.0-alpha.3 through versions prior to 0.5.0
  • Elixir and Erlang applications using Oidcc.Plug.Authorize for OpenID Connect flows
  • Deployments that opted into the user agent binding via check_useragent: true

Discovery Timeline

  • 2026-08-04 - CVE-2026-66883 published to NVD
  • 2026-08-04 - Last updated in NVD database

Technical Details for CVE-2026-66883

Vulnerability Analysis

The vulnerability resides in two files: lib/oidcc/plug/authorize.ex and lib/oidcc/plug/authorization_callback.ex. During the initial authorization request, Oidcc.Plug.Authorize.call/2 reads the client user agent using get_req_header(conn, "User-Agent"). Because Plug normalizes incoming header names to lowercase but get_req_header/2 performs an exact key match, the lookup never returns the actual header value. The function stores nil as the user agent in the session.

On the callback side, Oidcc.Plug.AuthorizationCallback.call/2 treats a stored nil user agent as "nothing to compare" and returns :ok without inspecting the incoming request. The two behaviors combine so the binding check passes unconditionally on every request. Impact is limited to defense in depth: CSRF/state, nonce, and PKCE checks remain functional and are unaffected.

Root Cause

The root cause is an inconsistency between how Plug stores header keys (lowercase) and how the caller queries them (mixed case). The corresponding lookup in Oidcc.Plug.AuthorizationCallback correctly uses the lowercase key "user-agent", exposing the asymmetry. Because the failure is silent, operators cannot detect that the binding is absent through logs or errors.

Attack Vector

An attacker who obtains a valid session artifact, such as an exfiltrated session cookie, can replay it from a different user agent to complete the authorization callback. The stolen-session replay succeeds without triggering the user agent mismatch defense that operators believed they had enabled. Exploitation requires prior compromise of a session token; the flaw does not directly grant an attacker the ability to initiate or complete an authorization flow on its own.

text
     pkce_verifier = 96 |> :crypto.strong_rand_bytes() |> Base.url_encode64(padding: false)

     peer_ip = conn.remote_ip
-    useragent = conn |> get_req_header("User-Agent") |> List.first()
+    useragent = conn |> get_req_header("user-agent") |> List.first()

     authorization_opts =
       opts

Source: GitHub Commit f15e52c. The patch changes the header lookup key from "User-Agent" to "user-agent", aligning it with Plug's lowercase normalization so the stored value is no longer nil.

Detection Methods for CVE-2026-66883

Indicators of Compromise

  • Session cookies used from client user agents that differ from the user agent that initiated the OpenID Connect flow.
  • Successful authorization callbacks with no corresponding session initiation from the same client fingerprint.
  • Absence of any log entry indicating a user agent mismatch, despite check_useragent: true being configured.

Detection Strategies

  • Audit deployed oidcc_plug versions across Elixir and Erlang services and flag any release between 0.1.0-alpha.3 and versions prior to 0.5.0.
  • Inspect application logs for stored session data containing nil in the user agent field when the configuration expects a populated value.
  • Correlate authorization initiation events with callback events and alert on user agent divergence at the reverse proxy or web server layer.

Monitoring Recommendations

  • Log the User-Agent header at both the authorize and callback steps at the infrastructure layer, independent of the library.
  • Monitor for anomalous session reuse patterns such as callbacks completing from geographies or client types not seen during authorization.
  • Track deployment inventories to confirm the presence of oidcc_plug0.5.0 or later after patching.

How to Mitigate CVE-2026-66883

Immediate Actions Required

  • Upgrade oidcc_plug to version 0.5.0 or later in all affected Elixir and Erlang applications.
  • Review deployments that set check_useragent: true and treat the binding as having been inert until the upgrade completes.
  • Rotate any session material suspected of exposure while the check was silently disabled.

Patch Information

The fix is available in commit f15e52c5750aaba701104b10ed96cfac063bd557, which corrects the header lookup key to "user-agent". Details are documented in GHSA-w5r8-m75h-98fc, the CNA advisory, and the OSV report EEF-CVE-2026-66883.

Workarounds

  • If immediate upgrade is not possible, enforce user agent consistency at the reverse proxy or API gateway by comparing headers between authorization and callback requests.
  • Reduce session cookie lifetimes to shrink the replay window available to an attacker holding a stolen session artifact.
  • Continue to rely on CSRF/state, nonce, and PKCE checks, which remain functional and provide the primary defenses against forged authorization flows.
bash
# Update oidcc_plug in mix.exs to the patched version
# {:oidcc_plug, "~> 0.5.0"}
mix deps.update oidcc_plug
mix deps.get

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

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

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.