CVE-2026-58228 Overview
CVE-2026-58228 is a cross-site scripting (XSS) vulnerability [CWE-79] in the Phoenix LiveView framework for Elixir. The flaw allows attackers to bypass URL scheme validation in the Phoenix.LiveView.Utils.valid_destination!/2 and Phoenix.LiveView.Utils.valid_live_navigation_destination!/2 functions. By prefixing a javascript: URL with an ASCII control character or space, attackers can trick the framework into treating a malicious URL as a safe relative path. The vulnerability affects phoenix_live_view versions 1.2.2 through 1.2.6 and is fixed in version 1.2.7.
Critical Impact
Attackers can execute arbitrary JavaScript in a victim's browser session when the victim clicks a crafted link rendered through <.link href={...}>, leading to session hijacking, credential theft, or unauthorized actions performed as the victim.
Affected Products
- Phoenix LiveView 1.2.2
- Phoenix LiveView versions 1.2.3 through 1.2.6
- Applications rendering user-supplied URLs via <.link href={...}>
Discovery Timeline
- 2026-07-13 - CVE CVE-2026-58228 published to NVD
- 2026-07-13 - Last updated in NVD database
Technical Details for CVE-2026-58228
Vulnerability Analysis
The vulnerability resides in the URL scheme validation logic within lib/phoenix_live_view/utils.ex. The internal uri_scheme/1 helper only detects a scheme when the input's first byte is an ASCII letter (A-Z or a-z). Inputs beginning with any other byte, including ASCII C0 control characters (0x00-0x1F) or space (0x20), fall through to a nil-returning clause.
When uri_scheme/1 returns nil, the framework treats the URL as a safe relative path and passes it unchanged to the rendered anchor tag. This creates a parsing discrepancy between the server-side validation and the browser's WHATWG URL parser.
Root Cause
The root cause is a mismatch between Phoenix LiveView's scheme detection and browser URL parsing behavior. Standard browsers implement the WHATWG URL specification, which strips leading C0 control characters and spaces before parsing a URL. Phoenix LiveView's validator does not perform this normalization, so an input like " javascript:alert(1)" bypasses the javascript: scheme block on the server but is parsed as a javascript: URL by the browser.
Attack Vector
An attacker submits a URL containing a leading control character or space followed by javascript: and a payload. The application stores this input, for example as a profile link, redirect target, or external reference. When the URL is rendered through <.link href={user_url}> and a victim clicks the link, the browser strips the leading whitespace and executes the JavaScript payload in the victim's session context.
# Returns the lowercased URI scheme of `to` if it begins with one, that is, a
# ":" appears before any "/", "?" or "#"; otherwise returns nil. This avoids
# treating a colon in a path segment, query, or fragment as a scheme.
- defp uri_scheme(<<char, _::binary>> = to) when char in ?A..?Z or char in ?a..?z do
+ defp uri_scheme(to) do
case :binary.match(to, [":", "/", "?", "#"]) do
- {pos, 1} when binary_part(to, pos, 1) == ":" ->
- String.downcase(binary_part(to, 0, pos), :ascii)
+ {pos, 1} ->
+ if binary_part(to, pos, 1) == ":",
+ do: String.downcase(binary_part(to, 0, pos), :ascii),
+ else: nil
- _ ->
+ :nomatch ->
nil
end
end
-
- defp uri_scheme(_to), do: nil
end
Source: GitHub Commit 86165533. The patch removes the pattern match on ASCII letters, ensuring all inputs are scanned for a scheme delimiter regardless of their first byte.
Detection Methods for CVE-2026-58228
Indicators of Compromise
- Stored user-supplied URL fields containing leading whitespace or control characters followed by javascript:, data:, or vbscript: schemes.
- HTTP request logs showing form or API submissions with URL parameters starting with %00, %20, or other percent-encoded control bytes preceding a scheme.
- Unexpected outbound requests or DOM modifications originating from anchor clicks on user-generated content pages.
Detection Strategies
- Audit database columns storing user-provided URLs for values matching a regex such as ^[\\x00-\\x20]+(javascript|data|vbscript):.
- Inspect rendered HTML output for <a href> attributes with leading whitespace or control characters preceding a colon.
- Review Phoenix LiveView application logs for <.link> component usage with dynamic href values sourced from untrusted input.
Monitoring Recommendations
- Enable Content Security Policy (CSP) reporting to capture script-src and inline-script violations that would result from successful exploitation.
- Monitor web application firewall (WAF) alerts for URL parameters containing encoded control characters followed by scheme keywords.
- Track dependency versions across Elixir projects and alert on phoenix_live_view releases between 1.2.2 and 1.2.6.
How to Mitigate CVE-2026-58228
Immediate Actions Required
- Upgrade phoenix_live_view to version 1.2.7 or later by updating the dependency in mix.exs and running mix deps.update phoenix_live_view.
- Audit all templates using <.link href={...}> with dynamic values and validate that URL inputs are sanitized before rendering.
- Scan existing stored user data for URLs beginning with control characters or whitespace followed by dangerous schemes.
Patch Information
The fix is available in phoenix_live_view version 1.2.7. The patch, applied in commit 86165533e311469a1b62093fd182d9d874de8106, rewrites uri_scheme/1 to scan all inputs for scheme delimiters rather than gating detection on the first byte being an ASCII letter. See the GitHub Security Advisory GHSA-5cgh-g58j-m9cq and the CNA CVE-2026-58228 Report for full details.
Workarounds
- Implement application-level URL validation that trims leading whitespace and C0 control characters before passing values to <.link href={...}>.
- Explicitly reject any URL input matching schemes such as javascript:, data:, or vbscript: after normalization.
- Deploy a strict Content Security Policy that disallows inline script execution to reduce the impact of any residual XSS vectors.
# Configuration example - update mix.exs dependency
# {:phoenix_live_view, "~> 1.2.7"}
mix deps.update phoenix_live_view
mix deps.get
mix compile
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

