Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
MEDIUM severity

CVE-2026-59923 — mistune

MEDIUMFix: lepture/mistune@c7101fc

CVE-2026-59923 is a medium-severity (CVSS 6.1) Cross-site Scripting (XSS) vulnerability in mistune. A fix is available for mistune — see the affected versions and patch details below.

Mistune: XSS via percent-encoded javascript URI bypass in safe_url()

Also known asGHSA-8c25-4j27-2rv3PYSEC-2026-2211
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 24, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-59923.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs27th percentile — riskier than 27% of all scored CVEsHighest risk
0.00%0.28%0.57%0.85%0.2%0.3%0.3%0.3%Aug 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-59923 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 395,308 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐍mistune

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

An XSS vulnerability in Mistune allows bypassing of safe_url() protections via percent-encoded javascript URIs.

Details

The vulnerability exists in HTMLRenderer.safe_url() 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.HARMFUL_PROTOCOLS):
    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 safe_url() protection mechanism.

PoC

  1. Install vulnerable version:

    pip install mistune==3.2.0

  2. Run the following code:

    import mistune

    markdown = mistune.create_markdown() 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.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPImistuneall versions3.3.0pip install --upgrade 'mistune==3.3.0'

Affected Products

1 product · 1 configurations
Application
mistunemistune_project
< 3.3.0
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for mistune, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update mistune to 3.3.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-59923 is resolved across your whole dependency graph.

  3. Workarounds

    Escape or sanitise the affected output on the server side rather than relying on client-side filtering, and add a Content-Security-Policy that blocks inline script execution so injected markup cannot run even if it reaches the page.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatModerate

Red Hat products ship python-mistune in both the older 0.8.x series and newer 3.x series. The URL sanitization bypass applies to both versions: the 0.8.x escape_link() function and the 3.x safe_url() function both fail to decode percent-encoded characters before checking for dangerous URI schemes. Exploitation…

Workaround published by Red Hat
Applications that render user-supplied Markdown with mistune can pass the HTML output through a dedicated HTML sanitizer such as bleach or nh3 before serving it to users. This removes dangerous URI schemes regardless of encoding.
Source: Red Hat security advisory for CVE-2026-59923 (CC BY 4.0)

Frequently Asked Questions

### Summary An XSS vulnerability in Mistune allows bypassing of safe_url() protections via percent-encoded javascript URIs. ### Details The vulnerability exists in HTMLRenderer.safe_url() 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.HARMFUL_PROTOCOLS): 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
O3 Security · Impact-Aware SCA

Is CVE-2026-59923 in your dependencies?

Find it across PyPI, including transitive dependencies.

CVE-2026-59923: mistune XSS — Fixed in 3.3.0