{"id":"CVE-2026-66883","state":"PUBLISHED","title":"Oidcc.Plug.Authorize user agent session binding inert due to case-sensitive header lookup","description":"Improper Handling of Case Sensitivity vulnerability in Erlang Ecosystem Foundation oidcc_plug (Oidcc.Plug.Authorize module) renders the user agent session binding inert, removing a defense in depth control against replay of a stolen session.\n\nThis vulnerability is associated with program files lib/oidcc/plug/authorize.ex and lib/oidcc/plug/authorization_callback.ex, and program routines Oidcc.Plug.Authorize.call/2 and Oidcc.Plug.AuthorizationCallback.call/2.\n\nOidcc.Plug.Authorize.call/2 reads the initiating client's user agent with get_req_header(conn, \"User-Agent\"). Plug lowercases incoming header names, but get_req_header/2 matches the supplied key exactly and performs no normalization of its own, so the mixed-case lookup always returns an empty list and nil is written into the session. On the callback side, Oidcc.Plug.AuthorizationCallback treats a stored nil user agent as nothing to compare and returns :ok without inspecting the request. The two behaviours combine so that the check passes unconditionally on every request, including for deployments that explicitly opted in with check_useragent: true, and an authorization callback can be completed from a different user agent than the one that initiated the flow without detection. The check fails open silently, with no error and no log entry, so a deployment cannot tell the binding is absent.\n\nThe impact is limited to defense in depth. The inert check does not by itself allow an attacker to complete an authorization flow; it removes one layer that would otherwise hinder use of a stolen or leaked session, such as an exfiltrated session cookie replayed from a different client. The CSRF/state, nonce, and PKCE checks are unaffected and continue to function. Deployments that never enabled check_useragent are not affected in practice, since they never expected the binding. The corresponding lookup in Oidcc.Plug.AuthorizationCallback correctly uses the lowercase key and is not affected.\n\nThis issue affects oidcc_plug: from 0.1.0-alpha.3 before 0.5.0.","publishedAt":"2026-08-04T11:46:05.191Z","updatedAt":"2026-08-04T12:27:58.024Z","severity":{"score":6.3,"label":"Medium","version":"4.0","vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","source":"EEF"},"assigner":"EEF","products":["Erlang Ecosystem Foundation oidcc_plug"],"affected":[{"vendor":"Erlang Ecosystem Foundation","product":"oidcc_plug","packageName":"oidcc_plug","packageURL":"pkg:hex/oidcc_plug","defaultStatus":"unaffected","versions":[{"version":"0.1.0-alpha.3","status":"affected","lessThan":"0.5.0","versionType":"semver"}],"collectionURL":"https://repo.hex.pm","cpes":["cpe:2.3:a:erlef:oidcc_plug:*:*:*:*:*:erlang:*:*"],"modules":["Elixir.Oidcc.Plug.Authorize","Elixir.Oidcc.Plug.AuthorizationCallback"],"programFiles":["lib/oidcc/plug/authorize.ex","lib/oidcc/plug/authorization_callback.ex"],"programRoutines":[{"name":"'Elixir.Oidcc.Plug.Authorize':call/2"},{"name":"'Elixir.Oidcc.Plug.AuthorizationCallback':call/2"}],"repo":"https://github.com/erlef/oidcc_plug"},{"vendor":"Erlang Ecosystem Foundation","product":"oidcc_plug","packageName":"erlef/oidcc_plug","packageURL":"pkg:github/erlef/oidcc_plug","defaultStatus":"unaffected","versions":[{"version":"0a75fb139d8e2686d1b75e0d48962323d2181673","status":"affected","lessThan":"f15e52c5750aaba701104b10ed96cfac063bd557","versionType":"git"}],"collectionURL":"https://github.com","cpes":["cpe:2.3:a:erlef:oidcc_plug:*:*:*:*:*:erlang:*:*"],"modules":["Elixir.Oidcc.Plug.Authorize","Elixir.Oidcc.Plug.AuthorizationCallback"],"programFiles":["lib/oidcc/plug/authorize.ex","lib/oidcc/plug/authorization_callback.ex"],"programRoutines":[{"name":"'Elixir.Oidcc.Plug.Authorize':call/2"},{"name":"'Elixir.Oidcc.Plug.AuthorizationCallback':call/2"}],"repo":"https://github.com/erlef/oidcc_plug"}],"references":["https://github.com/erlef/oidcc_plug/security/advisories/GHSA-w5r8-m75h-98fc","https://cna.erlef.org/cves/CVE-2026-66883.html","https://osv.dev/vulnerability/EEF-CVE-2026-66883","https://github.com/erlef/oidcc_plug/commit/f15e52c5750aaba701104b10ed96cfac063bd557"],"weaknesses":["CWE-178"],"ingestedAt":"2026-10-29T20:12:41.951Z","source":{"repository":"CVEProject/cvelistV5","path":"cves/2026/66xxx/CVE-2026-66883.json","commit":"556c9d3a8cd17e218bb8e452ba7cd619a384ff47"},"raw":{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2026-66883","state":"PUBLISHED","datePublished":"2026-08-04T11:46:05.191Z","dateUpdated":"2026-08-04T12:27:58.024Z","assignerShortName":"EEF","assignerOrgId":"6b3ad84c-e1a6-4bf7-a703-f496b71e49db","dateReserved":"2026-07-28T04:15:10.240Z"},"containers":{"cna":{"title":"Oidcc.Plug.Authorize user agent session binding inert due to case-sensitive header lookup","descriptions":[{"lang":"en","value":"Improper Handling of Case Sensitivity vulnerability in Erlang Ecosystem Foundation oidcc_plug (Oidcc.Plug.Authorize module) renders the user agent session binding inert, removing a defense in depth control against replay of a stolen session.\n\nThis vulnerability is associated with program files lib/oidcc/plug/authorize.ex and lib/oidcc/plug/authorization_callback.ex, and program routines Oidcc.Plug.Authorize.call/2 and Oidcc.Plug.AuthorizationCallback.call/2.\n\nOidcc.Plug.Authorize.call/2 reads the initiating client's user agent with get_req_header(conn, \"User-Agent\"). Plug lowercases incoming header names, but get_req_header/2 matches the supplied key exactly and performs no normalization of its own, so the mixed-case lookup always returns an empty list and nil is written into the session. On the callback side, Oidcc.Plug.AuthorizationCallback treats a stored nil user agent as nothing to compare and returns :ok without inspecting the request. The two behaviours combine so that the check passes unconditionally on every request, including for deployments that explicitly opted in with check_useragent: true, and an authorization callback can be completed from a different user agent than the one that initiated the flow without detection. The check fails open silently, with no error and no log entry, so a deployment cannot tell the binding is absent.\n\nThe impact is limited to defense in depth. The inert check does not by itself allow an attacker to complete an authorization flow; it removes one layer that would otherwise hinder use of a stolen or leaked session, such as an exfiltrated session cookie replayed from a different client. The CSRF/state, nonce, and PKCE checks are unaffected and continue to function. Deployments that never enabled check_useragent are not affected in practice, since they never expected the binding. The corresponding lookup in Oidcc.Plug.AuthorizationCallback correctly uses the lowercase key and is not affected.\n\nThis issue affects oidcc_plug: from 0.1.0-alpha.3 before 0.5.0."}],"affected":[{"vendor":"Erlang Ecosystem Foundation","product":"oidcc_plug","packageName":"oidcc_plug","packageURL":"pkg:hex/oidcc_plug","defaultStatus":"unaffected","versions":[{"version":"0.1.0-alpha.3","status":"affected","lessThan":"0.5.0","versionType":"semver"}],"collectionURL":"https://repo.hex.pm","cpes":["cpe:2.3:a:erlef:oidcc_plug:*:*:*:*:*:erlang:*:*"],"modules":["Elixir.Oidcc.Plug.Authorize","Elixir.Oidcc.Plug.AuthorizationCallback"],"programFiles":["lib/oidcc/plug/authorize.ex","lib/oidcc/plug/authorization_callback.ex"],"programRoutines":[{"name":"'Elixir.Oidcc.Plug.Authorize':call/2"},{"name":"'Elixir.Oidcc.Plug.AuthorizationCallback':call/2"}],"repo":"https://github.com/erlef/oidcc_plug"},{"vendor":"Erlang Ecosystem Foundation","product":"oidcc_plug","packageName":"erlef/oidcc_plug","packageURL":"pkg:github/erlef/oidcc_plug","defaultStatus":"unaffected","versions":[{"version":"0a75fb139d8e2686d1b75e0d48962323d2181673","status":"affected","lessThan":"f15e52c5750aaba701104b10ed96cfac063bd557","versionType":"git"}],"collectionURL":"https://github.com","cpes":["cpe:2.3:a:erlef:oidcc_plug:*:*:*:*:*:erlang:*:*"],"modules":["Elixir.Oidcc.Plug.Authorize","Elixir.Oidcc.Plug.AuthorizationCallback"],"programFiles":["lib/oidcc/plug/authorize.ex","lib/oidcc/plug/authorization_callback.ex"],"programRoutines":[{"name":"'Elixir.Oidcc.Plug.Authorize':call/2"},{"name":"'Elixir.Oidcc.Plug.AuthorizationCallback':call/2"}],"repo":"https://github.com/erlef/oidcc_plug"}],"references":[{"url":"https://github.com/erlef/oidcc_plug/security/advisories/GHSA-w5r8-m75h-98fc","tags":["vendor-advisory","related"]},{"url":"https://cna.erlef.org/cves/CVE-2026-66883.html","tags":["related"]},{"url":"https://osv.dev/vulnerability/EEF-CVE-2026-66883","tags":["related"]},{"url":"https://github.com/erlef/oidcc_plug/commit/f15e52c5750aaba701104b10ed96cfac063bd557","tags":["patch"]}],"metrics":[{"cvssV4_0":{"Automatable":"NOT_DEFINED","Recovery":"NOT_DEFINED","Safety":"NOT_DEFINED","attackComplexity":"HIGH","attackRequirements":"PRESENT","attackVector":"NETWORK","baseScore":6.3,"baseSeverity":"MEDIUM","privilegesRequired":"NONE","providerUrgency":"NOT_DEFINED","subAvailabilityImpact":"NONE","subConfidentialityImpact":"NONE","subIntegrityImpact":"NONE","userInteraction":"NONE","valueDensity":"NOT_DEFINED","vectorString":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","version":"4.0","vulnAvailabilityImpact":"NONE","vulnConfidentialityImpact":"NONE","vulnIntegrityImpact":"LOW","vulnerabilityResponseEffort":"NOT_DEFINED"},"format":"CVSS","scenarios":[{"lang":"en","value":"GENERAL"}]}],"problemTypes":[{"descriptions":[{"cweId":"CWE-178","description":"CWE-178 Improper Handling of Case Sensitivity","lang":"en","type":"CWE"}]}],"providerMetadata":{"shortName":"EEF","orgId":"6b3ad84c-e1a6-4bf7-a703-f496b71e49db","dateUpdated":"2026-08-04T11:46:05.191Z"},"cpeApplicability":[{"nodes":[{"cpeMatch":[{"criteria":"cpe:2.3:a:erlef:oidcc_plug:*:*:*:*:*:erlang:*:*","versionEndExcluding":"0.5.0","versionStartIncluding":"0.1.0-alpha.3","vulnerable":true}],"negate":false,"operator":"OR"}],"operator":"AND"}],"credits":[{"lang":"en","type":"finder","value":"Mathias Polligkeit"},{"lang":"en","type":"remediation developer","value":"Jonatan Männchen / EEF"},{"lang":"en","type":"remediation reviewer","value":"Mathias Polligkeit"},{"lang":"en","type":"coordinator","value":"Jonatan Männchen / EEF"}],"impacts":[{"capecId":"CAPEC-60","descriptions":[{"lang":"en","value":"CAPEC-60 Reusing Session IDs (aka Session Replay)"}]}],"source":{"discovery":"EXTERNAL"}},"adp":[{"title":"CISA ADP Vulnrichment","references":[{"url":"https://github.com/erlef/oidcc_plug/security/advisories/GHSA-w5r8-m75h-98fc","tags":["exploit"]}],"metrics":[{"other":{"type":"ssvc","content":{"timestamp":"2026-08-04T12:27:16.535019Z","id":"CVE-2026-66883","options":[{"Exploitation":"poc"},{"Automatable":"no"},{"Technical Impact":"partial"}],"role":"CISA Coordinator","version":"2.0.3"}}}],"providerMetadata":{"shortName":"CISA-ADP","orgId":"134c704f-9b21-4f2e-91b3-4a467353bcc0","dateUpdated":"2026-08-04T12:27:58.024Z"}}]}}}