CVE-2026-33079: Verified Repro With Script Download
CVE-2026-33079: Mistune: ReDoS via catastrophic backtracking in LINK TITLE RE
CVE-2026-33079 is verified against mistune · pip. Affected versions: >=3.0.0a1, <=3.2.0. Fixed in 3.2.1. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00148.
What Is CVE-2026-33079?
CVE-2026-33079 is a high-severity Regular-expression Denial of Service (ReDoS, CWE-1333) in the mistune Markdown parser's LINK_TITLE_RE regular expression, letting a tiny crafted document hang any renderer for multiple seconds. Pruva reproduced it (reproduction REPRO-2026-00148).
CVE-2026-33079 Severity & CVSS Score
CVE-2026-33079 is rated high severity, with a CVSS base score of 7.5 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected mistune Versions
mistune · pip versions >=3.0.0a1, <=3.2.0 are affected.
How to Reproduce CVE-2026-33079
pruva-verify REPRO-2026-00148 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00148/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-33079
Reproduced by Pruva's autonomous agents — 130 tool calls over 15 min. Full root-cause analysis and the complete transcript are below.
How the agent worked
Root Cause and Exploit Chain for CVE-2026-33079
Summary
The mistune Markdown parser (versions 3.0.0a1 through 3.2.0) contains a Regular-expression Denial of Service (ReDoS) vulnerability in the LINK_TITLE_RE regular expression used during inline link parsing. The regex contains overlapping alternatives inside a repeated group: an escaped-punctuation branch (\\ + PUNCTUATION) and a single-character branch ([^"\x00]). For input sequences such as \!, the regex engine can match the sequence either as one escaped-punctuation token or as two single-character tokens, leading to exponential backtracking when no closing quote is found. A crafted 58-byte Markdown document containing a link title with repeated backslash-escaped exclamation marks and no closing quote causes the renderer to hang for multiple seconds, enabling denial-of-service against any application that renders attacker-controlled Markdown.
Impact
- Package:
mistune(PyPI) - Repository: https://github.com/lepture/mistune
- Affected versions:
3.0.0a1through3.2.0 - Fixed version:
3.2.1 - CVE: CVE-2026-33079
- Advisory: GHSA-8mp2-v27r-99xp
- CWE: CWE-1333 (Inefficient Regular Expression Complexity)
- Severity: High (CVSS 8.7)
- Consequences: Any code path that renders user-supplied Markdown through
mistune(e.g., blog comments, document uploads, chat messages) can be forced to consume excessive CPU time, causing the application to hang or become unresponsive.
Root Cause
The vulnerable LINK_TITLE_RE regex is defined in src/mistune/helpers.py:
LINK_TITLE_RE = re.compile(
r"[ \t\n]+("
r'"(?:\\' + PUNCTUATION + r'|[^"\x00])*"|' # "title"
r"'(?:\\" + PUNCTUATION + r"|[^'\x00])*'" # 'title'
r")"
)
Inside the repeated group (?: ... )*, the two alternatives overlap for certain two-character sequences:
- Alternative A:
\\+PUNCTUATION— matches a backslash followed by any punctuation character (e.g.,\!) - Alternative B:
[^"\x00]— matches any single character except"and null (e.g.,\then!as two separate repetitions)
For the sequence \!, the regex engine has two ways to match it inside the repeated group. For n consecutive \! sequences, there are 2^n possible matching paths. When the closing quote is missing, the engine must explore all of these paths before failing, resulting in exponential time complexity.
The fix (released in mistune==3.2.1) adds the backslash to the negated character classes, eliminating the overlap:
LINK_TITLE_RE = re.compile(
r"[ \t\n]+("
r'"(?:\\' + PUNCTUATION + r'|[^"\\\x00])*"|'
r"'(?:\\" + PUNCTUATION + r"|[^'\\\x00])*'"
r")"
)
With [^"\\\x00], the second alternative can no longer match a bare backslash, so \! can only be matched by Alternative A. This removes the exponential branching and reduces complexity to linear.
Fix commit range: git diff v3.2.0 v3.2.1 in the lepture/mistune repository.
Reproduction Steps
The reproduction is fully automated by repro/reproduction_steps.sh.
What the script does:
- Creates a fresh Python virtual environment.
- Installs the vulnerable version
mistune==3.2.0. - Renders a crafted 58-byte Markdown payload:
This payload contains 25 backslash-escaped exclamation marks inside an unclosed double-quoted link title.[x](y "\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!) - Measures wall-clock render time with a 5-second timeout.
- Installs the fixed version
mistune==3.2.1. - Repeats the timed render.
- Compares results and writes a JSON verdict.
Expected evidence:
- Vulnerable (
3.2.0): Render exceeds the 5-second timeout (RESULT: timeout,ELAPSED: ~5.0s). - Fixed (
3.2.1): Render completes in well under the timeout (RESULT: completed,ELAPSED: <0.01s).
Evidence
Log files produced by the reproduction script:
logs/mistune_3.2.0.log— vulnerable runlogs/mistune_3.2.1.log— fixed run
Key excerpts:
Vulnerable (3.2.0):
RESULT: timeout
ELAPSED: 5.0001s
Fixed (3.2.1):
RESULT: completed
ELAPSED: 0.0026s
OUTPUT_LENGTH: 46
Environment:
- Python 3.x
mistune==3.2.0(vulnerable) andmistune==3.2.1(fixed) installed from PyPI- Wall-clock timeout: 5 seconds
- Payload: 58 ASCII bytes
Recommendations / Next Steps
- Upgrade immediately to
mistune>=3.2.1. The fix is a single-character change in the regex character class (adding\\to the negated class) and carries no functional risk. - Input sanitization: If upgrading is not immediately possible, consider imposing a short CPU-time or wall-clock timeout on Markdown rendering operations, or pre-validating link syntax before passing to
mistune. - Regression testing: Add a ReDoS regression test to the project’s test suite using the 58-byte payload (or larger variants) to ensure the regex does not regress.
- General best practice: For regexes that process untrusted input, avoid overlapping alternatives inside unbounded repeated groups. Use tools such as
re2orregexwith linear-time guarantees, or statically analyze regexes for catastrophic backtracking.
Additional Notes
- Idempotency: The reproduction script was run twice consecutively with identical results, confirming idempotency.
- Payload size: The payload is deliberately small (58 bytes) to demonstrate that even tiny attacker inputs can trigger the hang.
- No external services required: The vulnerability is 100% in-process; no network, browser, or database is needed for reproduction.
- Limitations: The timeout value (5s) was chosen to clearly distinguish the vulnerable behavior from the fixed behavior. On slower CPUs, the timeout may need to be adjusted, but the exponential gap ensures the distinction remains obvious.
CVE-2026-33079 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
cd "$ROOT" && git clone --depth=100 https://github.com/lepture/mistune.git mistune_repoCloning into 'mistune_repo'...
cd "$ROOT/mistune_repo" && git diff v3.2.0 v3.2.1/bin/bash: line 1: cd: /mistune_repo: No such file or directory
Artifacts and Evidence for CVE-2026-33079
Scripts, logs, diffs, and output captured during the reproduction.
No artifacts available
How to Fix CVE-2026-33079
Upgrade mistune · pip to 3.2.1 or later.
FAQ: CVE-2026-33079
Which mistune versions are affected by CVE-2026-33079, and where is it fixed?
How severe is CVE-2026-33079?
Does CVE-2026-33079 lead to code execution or data exposure?
How can I reproduce CVE-2026-33079?
References for CVE-2026-33079
Authoritative sources for CVE-2026-33079 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.