CVE-2026-66884 Overview
CVE-2026-66884 is a Cross-Site Request Forgery (CSRF) vulnerability [CWE-352] in the Erlang Ecosystem Foundation oidcc_plug library, specifically the Oidcc.Plug.AuthorizationCallback module. The flaw allows an attacker to make a victim's browser complete an OpenID Connect (OIDC) authorization flow the victim never initiated. When a callback request arrives without an Oidcc.Plug.Authorize session, the call/2 function substitutes permissive defaults and every downstream check (nonce, state, PKCE, peer IP, user agent) returns :ok. The application then signs the victim in as the attacker. Affected versions include oidcc_plug from 0.2.0-beta.1 up to but not including 0.5.0.
Critical Impact
Attackers can force victim browsers to authenticate as the attacker, exposing victim actions to the attacker and enabling account takeover in applications that reuse the callback for account linking.
Affected Products
- Erlang Ecosystem Foundation oidcc_plug versions 0.2.0-beta.1 through 0.4.x
- Elixir/Erlang applications using Oidcc.Plug.AuthorizationCallback for OIDC sign-in
- Applications that reuse a single callback endpoint for both sign-in and provider account linking
Discovery Timeline
- 2026-08-04 - CVE-2026-66884 published to NVD
- 2026-08-04 - Last updated in NVD database
Technical Details for CVE-2026-66884
Vulnerability Analysis
The vulnerability resides in lib/oidcc/plug/authorization_callback.ex in the Oidcc.Plug.AuthorizationCallback.call/2 routine. A callback request that carries no Oidcc.Plug.Authorize session should be rejected. Instead, call/2 fills in permissive defaults for the missing session values. Each downstream security check then compares its expected value against nothing and returns :ok. This bypasses nonce, state, PKCE, peer IP, and user agent validation entirely. A separate clause of check_state/2 also accepts a state-less request when a PKCE verifier is present, widening the bypass.
Root Cause
The root cause is a design flaw in error handling: the absence of a session is treated as a benign edge case rather than a hard failure. No conforming OIDC flow reaches this callback without a session. Oidcc.Plug.Authorize always sends a state parameter, which the authorization server must echo. The library also implements no third-party-initiated login endpoint, so the permissive fallback serves no legitimate flow.
Attack Vector
An attacker obtains an authorization code for their own OIDC provider account. The attacker then induces the victim (through a crafted link or embedded resource) to visit the callback endpoint with that authorization code and no state parameter. Because all security checks are skipped, the application signs the victim in as the attacker. Subsequent victim actions occur inside the attacker's account, where the attacker can read them. In applications that reuse one callback endpoint for both sign-in and provider account linking, the attacker's provider account becomes linked to the victim's application account, resulting in account takeover.
| :oidcc_userinfo.error()
| :useragent_mismatch
| :peer_ip_mismatch
+ | :missing_authorize_session
+ | :state_not_verified
| {:missing_request_param, param :: String.t()}
@impl Plug
Source: GitHub Commit 97d75afc. The patch adds two new error variants, :missing_authorize_session and :state_not_verified, so call/2 rejects callbacks that cannot be validated instead of substituting defaults.
Detection Methods for CVE-2026-66884
Indicators of Compromise
- Callback requests to the OIDC callback endpoint that omit the state query parameter
- Successful sign-ins immediately followed by session activity from an IP or user agent that differs from the sign-in request
- Authorization code values in callback URLs that do not match any code previously issued to the local relying party
- Newly linked provider identities in account-linking flows without a corresponding user-initiated link request
Detection Strategies
- Inspect web server and application logs for callbacks lacking state, nonce, or PKCE parameters
- Correlate OIDC callback events with prior Oidcc.Plug.Authorize events to identify orphan callbacks with no matching session
- Alert on downstream code returning :ok for security checks when the compared value is empty or nil
Monitoring Recommendations
- Enable verbose logging in oidcc_plug for callback validation outcomes and forward to a centralized log platform
- Monitor for spikes in authentication events where sign-in IP and post-sign-in IP diverge within a single session
- Track account-linking events and alert when linking occurs without a preceding authenticated user action
How to Mitigate CVE-2026-66884
Immediate Actions Required
- Upgrade oidcc_plug to version 0.5.0 or later across all Elixir and Erlang applications
- Audit application logs for callback requests missing the state parameter since oidcc_plug was deployed
- Review provider account links created during the vulnerable window and unlink any suspicious associations
- Force re-authentication for all active sessions after upgrading
Patch Information
The fix is available in oidcc_plug0.5.0. The patch commit is 97d75afc, which introduces the :missing_authorize_session and :state_not_verified error paths so callbacks without a valid authorize session are rejected. See the GitHub Security Advisory GHSA-fg66-w5gp-22cr and the CNA advisory for full technical detail.
Workarounds
- Place a reverse-proxy or middleware rule in front of the callback endpoint that rejects requests missing the state query parameter
- Separate sign-in and account-linking flows onto distinct callback endpoints to prevent unauthorized linking
- Require an anti-CSRF token bound to the initiating session on the callback route until the upgrade is deployed
# Update oidcc_plug dependency in mix.exs
# {:oidcc_plug, "~> 0.5.0"}
mix deps.update oidcc_plug
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.

