Mistune: Denial of Service — RecursionError via Excessive Emphasis Markers in Markdown
Summary
Mistune v3.3.2 is vulnerable to a Denial of Service (DoS) attack via uncontrolled recursion in the HTML rendering of deeply-nested emphasis tokens. By submitting Markdown containing approximately 1,000 consecutive asterisk characters, an attacker causes the Python process to crash with RecursionError.
Details
The InlineParser's _process_emphasis_delimiters() creates deeply nested <strong> tokens from consecutive emphasis markers (every 2 asterisks add one nesting level). With 1,000 consecutive asterisks, approximately 500 levels of nesting are produced. The HTMLRenderer.render_token() method (src/mistune/renderers/html.py:40-57) renders these tokens recursively: when a token has children, line 48 calls self.render_tokens(token['children'], state), entering child rendering. Each nesting level produces ~2 stack frames, so 500 levels ≈ 1,000 frames, exceeding Python's default recursion limit (sys.getrecursionlimit() = 1000). The emphasis() and strong() methods (lines 80-84) wrap recursively rendered child content in <em> and <strong> tags, perpetuating the recursion. This vulnerability affects all mistune APIs including markdown() and html().
Core vulnerable code path:
# src/mistune/renderers/html.py:40-57
def render_token(self, token: Dict[str, Any], state: BlockState) -> str:
func = self._get_method(token["type"])
attrs = token.get("attrs")
if "raw" in token:
text = token["raw"]
elif "children" in token:
text = self.render_tokens(token["children"], state)
else:
if attrs:
return func(**attrs)
else:
return func()
if attrs:
return func(text, **attrs)
else:
return func(text)
The recursive call to render_tokens() on line 48 processes nested child tokens. With 500 levels of nested emphasis/strong tokens, this recursion exceeds Python's default recursion limit of 1000, causing a RecursionError.
# src/mistune/renderers/html.py:80-84
def emphasis(self, text: str) -> str:
return "<em>" + text + "</em>"
def strong(self, text: str) -> str:
return "<strong>" + text + "</strong>"
The emphasis() and strong() methods wrap their text content (which is itself the recursively-rendered output of nested child tokens) in HTML tags, creating the chain of recursion: each call to strong() includes rendered children that themselves call strong(), etc.
POC
from mistune import html
payload = '*' * 1000
try:
result = html(payload)
print('No crash - recursion handled')
except RecursionError as e:
print(f'[VULN] RecursionError: {e} - Process would crash!')
except Exception as e:
print(f'Error: {type(e).__name__}: {e}')
Impact
CVSS 3.1: 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. An attacker can crash any server process using mistune with approximately 2KB of Markdown input. In web applications, this can be triggered through user-generated content such as forum posts or comments, causing denial of service for all concurrent users sharing the same Python process. Both mistune.markdown() and mistune.html() are affected.
Remediation
- Add a maximum nesting depth limit in the emphasis parsing stage, similar to BlockParser's max_nested_level mechanism (currently at DEFAULT_MAX_NESTED_LEVEL = 20). When the limit is exceeded, treat excess emphasis markers as literal text. 2. Alternatively, refactor HTMLRenderer to use an explicit stack-based iterative approach instead of recursive calls for rendering nested tokens. 3. As a defense-in-depth measure, document the recursion risk and recommend that applications deploying mistune set a higher recursion limit or implement request-level timeouts.
Software afectado
Haz clic en una tecnología para ver todas sus vulnerabilidades.
| Plataforma | Paquete | Versiones vulnerables | Corregida en |
|---|---|---|---|
| Python (PyPI) | mistune | >= 3.3.0, < 3.3.3 | 3.3.3 |
Referencias
- https://github.com/lepture/mistune/security/advisories/GHSA-6m44-fpc8-c3rq
- https://nvd.nist.gov/vuln/detail/CVE-2026-76098
- https://github.com/lepture/mistune/commit/0938fb781d0aded99de801b340ec1f8debeae5b2
- https://github.com/lepture/mistune
- https://github.com/lepture/mistune/releases/tag/v3.3.3
- https://pypi.org/project/mistune
- https://github.com/advisories/GHSA-6m44-fpc8-c3rq
- Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H- Debilidad (CWE)
CWE-674- Plataforma
- Python (PyPI)
- Paquete
mistune- Publicada
- 02.09.2026
- Actualizado
- 11.10.2026 15:18
Fuentes y licencias
OSV / GitHub Advisory Database - PYSEC-2026-3863 - PyPA Advisory Database; CC BY 4.0
OSV / GitHub Advisory Database - GHSA-6m44-fpc8-c3rq - CC BY 4.0
Historial de vulnerabilidades: mistune
Todas las vulnerabilidades publicadas de este paquete (Python (PyPI)), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.
- Entradas en total
- 20
- Primera → última
- 10.2017 09.2026
- Sin corrección
- 1
- Explotada en ataques
- 0
Distribución por gravedad
- Alta 7
- Media 13
Divulgaciones por año
- 2017: 2
- 2018: 0
- 2019: 0
- 2020: 0
- 2021: 0
- 2022: 1
- 2023: 0
- 2024: 0
- 2025: 0
- 2026: 17
-
Mistune: Denial of Service — RecursionError via Excessive Emphasis Markers in Markdown esta entrada
Identifica las vulnerabilidades de tu aplicación
Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.