CVE-2026-59928: Mistune block_parser: quadratic-time parsing on long lists of repeated reference-link definitions

Published Jul 8, 2026
·
Updated

Summary

Type: Algorithmic-complexity DoS in reference-link definition handling. A markdown document with N reference-link definitions of the same key (or many distinct keys) takes O(N²) parser time. 5000 repeated [a]: u\n definitions take ~1.1 second; 10000 → ~4.5 seconds. File: src/mistune/blockparser.py (reference-link def parsing) and the surrounding reflinks env-dictionary handling. Root cause: every reference definition is parsed by scanning forward from each candidate position. The unikey normalisation runs per-def, the dictionary insert is per-def, and the lookup-by-label-then-iterate-defs path is linear in the number of stored defs. For input with N defs, the total work is O(N²).

Affected Code

src/mistune/blockparser.py — reference-definition rule fires on every line that matches [label]: url. For each one: - unikey(label) is called (linear scan of the label). - The def is appended to state.env['reflinks']. - Later inline-link resolution looks up by unikey(label) in the dict (O(1)) but the surrounding parser revisits the def list for paragraph-vs-def disambiguation.

The cumulative parse time grows as the square of the number of defs.

Why it's wrong: the parser does not amortise the def-list scan. A single forward pass with a hash-keyed dict (already in place) plus a per-line classifier should make this O(N).

Exploit Chain

1. Application uses mistune to render attacker-supplied markdown. No plugins required. 2. Attacker submits a 35 KB document of [a]: u\n repeated 5000 times followed by [click][a]. 3. CPU pegs for ~1.1 seconds. 10000 defs → ~4.5 s. 20000 → ~18 s. Doubling input quadruples time.

Security Impact

Attacker capability: small input → large CPU. Predictable scaling. Can be repeated. Preconditions: application uses mistune.createmarkdown() (default config) on attacker-supplied markdown. Worth noting: the reflinks dictionary persists for the lifetime of the parse, so a long document with many defs builds up memory; with N defs of attacker-chosen length, the per-def normalisation cost compounds. Differential: PoC-verified against mistune@3.2.1, default config:

python import mistune, time md = mistune.createmarkdown() for n in [1000, 2000, 5000, 10000]: s = '[a]: u\n' n + '[click][a]' t = time.time() md(s) print(f' ref defs {n} ({len(s)}b): {(time.time() - t) 1000:.0f}ms')

Output (Python 3.13, Linux, 2.5GHz CPU): ref defs 1000 ( 7012b): 46ms ref defs 2000 (14012b): 186ms ref defs 5000 (35012b): 1121ms ref defs 10000 (70012b): 4400ms

The patched build (with the surrounding parser amortised to O(N)) keeps the time linear.

Suggested Fix

Replace the per-def re-scan with a single forward pass that classifies each line into refdef | paragraph | other once and only inserts into reflinks once per def. The dict already exists; the wasted work is in the surrounding scan loop, not in the dict operations.

A regression test asserting that md('[a]: u\n' 50000 + '[click][a]') completes in under 1 second would catch any regression.

Other sources

Mistune is a Python Markdown parser with renderers and plugins. Prior to 3.3.0, a Markdown document containing many repeated or distinct reference-link definitions causes quadratic work in src/mistune/blockparser.py and the reflinks environment dictionary handling, allowing denial of service through CPU exhaustion. This issue is fixed in version 3.3.0.

MITRE

Affected Software

3 affected componentsFixes available
Mistune Mistune<3.3.0
Mistune Project Mistune<3.3.0
pip/mistune<3.3.0
3.3.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/mistune to a version that resolves this vulnerability.

    Fixed in 3.3.0
  2. Upgrade

    Upgrade mistune to a version that resolves this vulnerability.

    Fixed in 3.3.0
  3. Compensating control

    Apply a request size / CPU-time limit for attacker-supplied Markdown rendered with mistune (e.g., cap the maximum Markdown length and/or abort rendering when parsing exceeds a threshold), since large numbers of repeated reference-link definitions like '[a]: u\n' repeated 5000 times cause ~O(N^2) CPU exhaustion in mistune versions prior to 3.3.0.

Event History

Jul 8, 2026
CVE Published
via MITRE·04:23 PM
Data Sourced
via MITRE·04:23 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·05:17 PM
RemedyDescriptionSeverityWeaknessAffected Software
Jul 20, 2026
Advisory Published
via GitHub·09:24 PM
Data Sourced
via GitHub·09:24 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What is the severity of CVE-2026-59928?

CVE-2026-59928 has a severity rating of 7.5, which is classified as high.

2

How do I fix CVE-2026-59928?

To fix CVE-2026-59928, update Mistune to version 3.3.0 or later.

3

What kind of vulnerability is CVE-2026-59928?

CVE-2026-59928 is a denial of service vulnerability due to quadratic-time parsing in Mistune.

4

Which software is affected by CVE-2026-59928?

CVE-2026-59928 affects the Mistune Markdown parser prior to version 3.3.0.

5

What causes the issue in CVE-2026-59928?

The issue in CVE-2026-59928 is caused by many repeated reference-link definitions leading to inefficient parsing.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203