Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessSend request with wrong-typed token param or missing header
-
ExploitFail Plug.Crypto function-head guard (FunctionClauseError)
-
ExecutionSecret key base written to error log and crash_reason metadata
-
ImpactRead 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. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – 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
Affected Packages
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
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
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.
Primary rating from Vendor (EEF).
CVSS VectorVendor: EEF
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
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.
What every action level means
SSVC AssessmentENISA
Priority Score
Denial of service in Elixir Plug 1.15.0 through 1.19.2 allows unauthenticated remote attackers to saturate BEAM schedule
Elixir Plug before v1.0.4, v1.1.7, v1.2.3 and v1.3.2 is vulnerable to arbitrary code execution in the deserialization fu
Memory exhaustion in Elixir Plug 1.4.0 through 1.19.1 allows remote unauthenticated attackers to crash BEAM VM processes
Elixir Plug before v1.0.4, v1.1.7, v1.2.3 and v1.3.2 is vulnerable to null byte injection in the Plug.Static component,
Elixir Plug Plug version All contains a Header Injection vulnerability in Connection that can result in Given a cookie v
EUVD-2026-108666
NVD
CVE.org
EPSS
Vulnrichment
GitHub
VulDB
Exploit-DB