CVE-2026-59927: Mistune directives/include: mutual `.. include::` recursion crashes the renderer with `RecursionError`, denial of service via two attacker-controlled markdown files
Type: Uncontrolled recursion via mutual include. The Include directive checks for direct self-reference (a.md cannot include a.md), but does not detect indirect cycles. Two markdown files that include each other (a.md → includes b.md → includes a.md) cause unbounded recursion until Python’s stack limit fires RecursionError. The exception propagates out of the renderer and crashes the calling code.
File: src/mistune/directives/include.py, lines 33-37 (the self-include check is the only cycle-detection logic).
Root cause: the include logic only compares os.path.abspath(dest) == os.path.abspath(source_file). There is no per-render set of “files already included” that would catch transitive cycles. When a.md includes b.md, the recursive block.parse(new_state) call uses dest (b.md) as the new __file__, which then includes a.md (passing the self-check, because the immediate parent file is b.md, not a.md), which then includes b.md, and so on. Each recursion level adds Python frames; the default stack limit of 1000 frames trips after ~7-10 cycle iterations and Python raises RecursionError. Since the directive does not catch the exception, it propagates out of Markdown.parse() and surfaces in the calling code, crashing the request.
References
- github.com/advisories/GHSA-8mpj-m6qm-5qr8
- github.com/lepture/mistune/commit/1bef343ade163fc3bb95572b15be720084cdb993
- github.com/lepture/mistune/releases/tag/v3.3.0
- github.com/lepture/mistune/security/advisories/GHSA-8mpj-m6qm-5qr8
- github.com/pypa/advisory-database/tree/main/vulns/mistune/PYSEC-2026-2215.yaml
- nvd.nist.gov/vuln/detail/CVE-2026-59927
Code Behaviors & Features
Detect and mitigate CVE-2026-59927 with GitLab Dependency Scanning
Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →