high · 7.5CVE-2026-49851Jul 10, 2026

CVE-2026-49851: mistune Quadratic-Time DoS in parse_link_text

Rohit Hatagale
AI Security Researcher, SecureLayer7

Sending a few thousand open-bracket characters to any app that parses user Markdown with mistune causes the CPU to spin for seconds, making denial-of-service trivially cheap.

Packagemistune
Ecosystempip
Affected< 3.3.0
Fixed in3.3.0

The problem

In mistune < 3.3.0, the outer loop in InlineParser.parse() advances one character at a time whenever parse_link() returns None. Each failed attempt calls parse_link_text(), which does a fresh O(n) regex scan looking for a closing ].

With n consecutive [ characters, the outer loop runs n times and each iteration scans up to n characters, giving O(n²) total work. A 6 KB payload (6400 brackets) causes roughly 3 seconds of CPU burn per request.

Proof of concept

A working proof-of-concept for CVE-2026-49851 in mistune, with the exact payload below.

python
import mistune
import time

md = mistune.create_markdown()

# 6400 open brackets, no closing bracket, no valid link
s = "[" * 6400

t = time.perf_counter()
md(s)
print(time.perf_counter() - t)  # ~3.2 s on a modern laptop

The root cause is a two-loop interaction: the outer parse loop never skips ahead when a link attempt fails, so it re-enters parse_link_text at every single character position. parse_link_text itself scans forward to find ], making each call O(n). The fix makes parse_link_text return the furthest position it reached even on failure, so the outer loop can jump past already-scanned input instead of advancing by one.

This is CWE-400 (Uncontrolled Resource Consumption) combined with CWE-1333 (Inefficient Regular Expression Complexity). No special privileges or authentication are needed; any endpoint that renders user-supplied Markdown is exposed.

The fix

Upgrade mistune to 3.3.0 or later (pip install --upgrade mistune). The 3.3.0 release patches parse_link_text in inline_parser.py to propagate the scan cursor forward on failure, breaking the O(n²) loop. No configuration change is needed after upgrading.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research