CVE-2026-59923: Mistune: XSS via percent-encoded javascript URI bypass in safe_url()
Summary An XSS vulnerability in Mistune allows bypassing of safeurl() protections via percent-encoded javascript URIs.
Details The vulnerability exists in HTMLRenderer.safeurl() in Mistune.
The function is intended to block harmful URL schemes such as "javascript:" by checking the prefix of the provided URL:
url = url.lower() if url.startswith(self.HARMFULPROTOCOLS): return "#harmful-link"
However, the input URL is not URL-decoded before this check. Because of this, an attacker can use percent-encoding to bypass the filter. For example:
javascript%3Aalert(1)
Since "%3A" is not decoded to ":", the check does not detect the "javascript:" scheme.
When rendered in a browser, the URL is decoded, resulting in execution of arbitrary JavaScript upon user interaction.
This effectively bypasses Mistune's built-in safeurl() protection mechanism.
PoC 1. Install vulnerable version:
pip install mistune==3.2.0
2. Run the following code:
import mistune
markdown = mistune.createmarkdown() html = markdown("j)")
print(html)
3. Output:
<p><a href="javascript%3Aalert(1)">j</a></p>
4. Open the rendered HTML in a browser and click the link.
5. The browser decodes "%3A" into ":" and executes:
javascript:alert(1)
Impact This is a cross-site scripting (XSS) vulnerability.
An attacker can craft a malicious Markdown link that executes JavaScript in the victim's browser when clicked.
Impact includes: - Session hijacking (e.g., cookie theft) - Execution of arbitrary JavaScript in the victim's context - Potential account takeover depending on the application
This affects any application that renders user-controlled Markdown using Mistune without additional URL sanitization.
Other sources
Mistune is a Python Markdown parser with renderers and plugins. Prior to 3.3.0, HTMLRenderer.safeurl() does not block percent-encoded javascript URIs, allowing attacker-supplied Markdown links or images to bypass URL protections and execute script in rendered HTML. This issue is fixed in version 3.3.0.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/mistuneto a version that resolves this vulnerability.Fixed in 3.3.0 - Upgrade
Upgrade
mistuneto a version that resolves this vulnerability.Fixed in 3.3.0 - Compensating control
If your application renders user-controlled Markdown with Mistune, apply additional URL sanitization beyond Mistune's HTMLRenderer.safe_url() (to prevent percent-encoded javascript: URIs) before rendering or before allowing links/images to be used.
Event History
Frequently Asked Questions
What is the severity of CVE-2026-59923?
The severity of CVE-2026-59923 is rated as medium with a CVSS score of 6.1.
How do I fix CVE-2026-59923?
To fix CVE-2026-59923, upgrade Mistune to version 3.3.0 or later.
What type of vulnerability is CVE-2026-59923?
CVE-2026-59923 is an cross-site scripting (XSS) vulnerability.
Who is affected by CVE-2026-59923?
Any user or application utilizing Mistune versions prior to 3.3.0 is at risk from CVE-2026-59923.
What does CVE-2026-59923 allow an attacker to do?
CVE-2026-59923 allows an attacker to bypass URL protections and potentially execute malicious scripts in rendered HTML.