Skip to main content

plug_crypto EUVDEUVD-2026-108666

| CVE-2026-105963 MEDIUM
Insertion of Sensitive Information into Log File (CWE-532)
2026-10-23 EEF
5.1
CVSS 4.0 · Vendor: EEF
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Send request with wrong-typed token param or missing header
  2. Exploit
    Fail Plug.Crypto function-head guard (FunctionClauseError)
  3. Execution
    Secret key base written to error log and crash_reason metadata
  4. Impact
    Read application logs or error tracker to recover secret

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A09:2025 - Security Logging & Alerting Failures
ASVS 5.0
V16 - Security Logging and Error Handling Log data sanitization
Exploitation Conditions

Requires an Elixir application that (1) calls Plug.Crypto.verify/4 (reachable via Phoenix.Token.verify/4, which forwards the token unguarded, so a controller passing params["token"] is enough), Plug.Crypto.decrypt/4, or Plug.Crypto.secure_compare/2 with a request-controlled operand (e.g. comparing List.first(get_req_header(conn, "x-api-key")) against a configured secret); and (2) runs under an adapter that logs the crash frame with its arguments - Plug.Cowboy or Bandit - while that log or crash_reason metadata is forwarded to an error tracker or stored unencrypted. Triggering needs no authentication and no user interaction (a wrong-typed param like token[]=x, a JSON token value, or a simply missing x-api-key header that yields nil). The decisive limiting factor is that the triggering request does not disclose the secret to the attacker: a separate party must have read access to the logs or error tracker, which is why the vector uses PR:H despite the unauthenticated trigger. Applications on plug_crypto >=2.2.1 and plug >=1.7.0 are not affected.

Impact

The CVSS 4.0 base score of 5.1 (medium) with vector AV:N/AC:L/AT:N/PR:H/UI:N/VC:L reflects a genuine but constrained risk. An unauthenticated network request carrying a wrong-typed parameter is enough to trigger the leak (a low-complexity trigger), but the vendor scored PR:H because actually reading the leaked secret requires separate privileged access to the application logs or error tracker. This two-actor split is the central tension: the description states an 'unauthenticated remote attacker' can trigger the FunctionClauseError, yet the disclosed secret only reaches someone who can read log/error-tracker output, so the request alone does not hand the secret to the triggering attacker - verify how your logs are protected and forwarded before rating this as a remote-read issue. No EPSS score was provided and the CVE is not in CISA KEV, so there is no signal of active or widespread exploitation; the vuln.today decision label is 'this_month', consistent with scheduled patching rather than emergency response. Exploitation status: no public exploit identified at time of analysis (only advisory and patch-commit references are present, not exploit code). The factor that raises real-world stakes above the modest score is the sensitivity of the disclosed data - the secret key base is sufficient to mint session cookies and tokens under any salt - so environments that forward logs to third-party error trackers or store them unencrypted should prioritize the fix.

Exploit ScenarioDerived

An attacker sends one unauthenticated request to a Phoenix/Plug application - for example 'token[]=x' in a query string so params["token"] becomes a list, a JSON body making it an integer or map, or simply omitting an 'x-api-key' header so secure_compare receives nil. The wrong-typed argument fails a Plug.Crypto function-head guard, the Erlang VM raises FunctionClauseError with the real argument values in the top stack frame, and Plug.Cowboy or Bandit write the secret key base (or the configured value an API key is compared against) into the error log and crash_reason Logger metadata. A party with read access to those logs or the forwarded error tracker then recovers the secret; no public exploit code was identified.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.7% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 23, 2026

Sensitive-value disclosure in Elixir's plug_crypto library allows a single unauthenticated request carrying a wrong-typed argument or a missing header to push the application's secret key base, a derived 32-byte encryption key, or the configured secret an API key is compared against into the Plug.Cowboy/Bandit error log and into crash_reason Logger metadata that error trackers forward. Applications on plug_crypto from 1.0.0 before 2.2.1, or on the bundled Plug.Crypto shipped in plug from 1.6.3 before 1.7.0, are affected; the request itself does not hand the secret to the attacker, so exploitation additionally depends on a separate party having read access to those logs or to the error tracker, which is why the assessed vector carries PR:H despite the unauthenticated trigger. No public exploit code was identified at time of analysis, and patched releases (plug_crypto 2.2.1, plug 1.7.0) are available from the vendor.

RemediationAI

Vendor-released patch: upgrade plug_crypto to 2.2.1 (fixes >= 1.0.0) and plug to 1.7.0 (fixes >= 1.6.3), per the GHSA-ffw9-w85g-f2vh advisory at https://github.com/elixir-plug/plug/security/advisories/GHSA-ffw9-w85g-f2vh; the corresponding upstream changes are commits 981887493dada0fce7003c61861c00dfbb0fc8c5 and 2d078b7b8264c565f0ff71235c515f4f46882dcf in plug_crypto and aeaa90e76b73ea90c3ecca9aae16fce71bd2a8d4 and 56000c33d8a0a2fbac491f8be06b9c5112bc2276 in plug, which add is_binary guards to secure_compare/2 and masked_compare/3 and apply Plug.Crypto.prune_args_from_stacktrace/1 in rescue blocks across KeyGenerator, MessageEncryptor and MessageVerifier. Because the leak only materializes once the frame is persisted, the vendor notes that logs shipped to external systems or stored without encryption are the exposure path, so until the upgrade is deployed, treat existing error logs and error-tracker crash_reason payloads as potentially containing the secret key base and derived keys, restrict read access to those systems, and rotate the secret key base (which invalidates existing sessions and signed tokens) if log exposure cannot be ruled out.

Affected VersionsENISA

plug_crypto 1.0.0 <2.2.1
plug 1.6.3 <1.7.0
plug_crypto 2d078b7b8264c565f0ff71235c515f4f46882dcf <981887493dada0fce7003c61861c00dfbb0fc8c5
plug 56000c33d8a0a2fbac491f8be06b9c5112bc2276 <*

Affected Packages

euvd plug fix: 1.7.0
euvd plug_crypto fix: 2.2.1

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 2 packages in euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Every public function in Plug.Crypto performs its argument type checking in a function-head guard. When a guard fails, the Erlang VM raises a FunctionClauseError whose top stack frame includes the actual argument values, and the library's rescue/reraise blocks together with Plug.Crypto.prune_args_from_stacktrace/1 only act on exceptions raised inside a function body, so they never observe a guard failure. Plug.Cowboy and Bandit write that frame, arguments included, to the error log and attach it as crash_reason Logger metadata, which error trackers forward. Two entry points are reachable with request data: Plug.Crypto.verify/4, where a token that is neither a binary nor nil (for example a list produced by token[]=x in a query string, or an integer/map from a JSON body) exposes the secret key base and is reachable through Phoenix.Token.verify/4 because that function forwards the token unguarded and guards only the salt; and Plug.Crypto.secure_compare/2, where a non-binary operand such as nil from a missing request header exposes the other operand, the configured secret it was compared against. Plug.Crypto.decrypt/4 with a non-binary token leaks the derived 32-byte key because the failing guard sits in MessageEncryptor.decrypt/4 after key derivation. The root cause class is CWE-532, insertion of sensitive information into log files; the fix adds a stacktrace-pruning helper, wires it into rescue clauses across KeyGenerator, MessageEncryptor and MessageVerifier, and adds explicit is_binary guards to secure_compare/2 and masked_compare/3. Notably, the assessed vector (CVSS 3.1 AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N) reflects that the trigger is remote and unauthenticated but the confidentiality loss requires high-privilege access to log or error-tracker infrastructure.

Know when Plug gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (EEF) PRIMARY 5.1 MEDIUM
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
vuln.today AI 4.9 MEDIUM

Trigger is a trivial unauthenticated request (AC:L), but reading the leaked secret needs privileged log/error-tracker access (PR:H); the disclosed secret key base enables full token forgery, so C:H, with no integrity or availability impact.

3.1 AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N
4.0 AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (EEF).

CVSS VectorVendor: EEF

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
None
Privileges Required
High
User Interaction
None
Vulnerable system: Confidentiality
Low
Vulnerable system: Integrity
None
Vulnerable system: Availability
None
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

DescriptionCVE.org

Externally-Generated Error Message Containing Sensitive Information vulnerability in plug_crypto in elixir-plug plug_crypto allows an unauthenticated remote attacker to expose the secret key base through application logs via a wrong-typed argument. Every public function in Plug.Crypto validates argument types in a function-head guard. A failed guard makes the Erlang VM raise FunctionClauseError with the actual argument values in the top stack frame, so the secret key base, a derived key, or the value an API key is compared against lands in that frame. The library's rescue blocks and Plug.Crypto.prune_args_from_stacktrace/1 only reach exceptions raised inside a function body, so they never see a guard failure. Plug.Cowboy and Bandit write the frame to the error log and attach it as crash_reason Logger metadata, which error trackers forward.

Two entry points take request data. Plug.Crypto.verify/4 exposes the secret key base when the token is neither a binary nor nil, which Phoenix.Token.verify/4 reaches because it forwards the token unguarded. Plug.Crypto.secure_compare/2 exposes the other operand when one side is not a binary, as happens when a missing request header yields nil. Reading the leaked value needs separate access to the logs or the error tracker, so the request alone does not disclose the secret to the attacker.

This issue affects plug: from 1.6.3 before 1.7.0; plug_crypto: from 1.0.0 before 2.2.1.

Threat Intelligence Overview

EPSS Score
0.7%
Top 47% exploitable
Prevalence
Medium
core crypto library in nearly all Elixir/Phoenix web apps; Elixir footprint modest overall
Social Media
1
Sightings
Data Quality
7 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment CIRCL GitHub VulDB

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.7%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
None
System Exposure· derived
Open
Automatable
No
Human Impact· derived
Medium
Technical Impact
Partial

Priority Score

27
Low Medium High Critical
KEV: 0
EPSS: +1
CVSS: +26
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy