VYPR
High severityNVD Advisory· Published Mar 3, 2021· Updated Aug 3, 2024

CVE-2021-26813

CVE-2021-26813

Description

markdown2 before 2.4.0 is vulnerable to regular expression denial of service (ReDoS) via crafted input causing catastrophic backtracking.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

markdown2 before 2.4.0 is vulnerable to regular expression denial of service (ReDoS) via crafted input causing catastrophic backtracking.

Root

Cause The python-markdown2 library (versions >= 1.0.1.18) contains multiple vulnerable regular expressions in markdown2.py that are susceptible to catastrophic backtracking. These patterns are used when certain extras (such as 'numbering' or 'fenced-code-blocks') are enabled. For example, the regex for numbered definitions (self.regex_defns) includes repeating groups that match spaces, leading to cubic time complexity on long strings of spaces [3].

Exploitation

An attacker can provide a specially crafted string as markdown input. No authentication or special privileges are required if the application processes user-supplied markdown. The attack is triggered by sending a string that includes a large number of repeating characters (e.g., spaces or newlines) that cause the regex engine to stall. This can be done remotely over the network [1].

Impact

Successful exploitation results in a denial of service condition. The processing of markdown becomes extremely slow or effectively hangs, consuming excessive CPU resources. This can disrupt the availability of the application using markdown2 [1][2].

Mitigation

The vulnerability is fixed in markdown2 version 2.4.0. Users should upgrade to this version or later to avoid the ReDoS issue. No workarounds are available for affected versions [1][3].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
markdown2PyPI
>= 1.0.1.18, < 2.4.02.4.0

Affected products

5

Patches

1
7b6512607396

Merge pull request #387 from trentm/regex-dos

https://github.com/trentm/python-markdown2Nicholas SerraJan 21, 2021via ghsa
1 file changed · +7 7
  • lib/markdown2.py+7 7 modified
    @@ -532,7 +532,7 @@ def parse_structured_value(value):
     
             return tail
     
    -    _emacs_oneliner_vars_pat = re.compile(r"-\*-\s*([^\r\n]*?)\s*-\*-", re.UNICODE)
    +    _emacs_oneliner_vars_pat = re.compile(r"-\*-\s*(?:(\S[^\r\n]*?)([\r\n]\s*)?)?-\*-", re.UNICODE)
         # This regular expression is intended to match blocks like this:
         #    PREFIX Local Variables: SUFFIX
         #    PREFIX mode: Tcl SUFFIX
    @@ -892,8 +892,8 @@ def _do_numbering(self, text):
             '''
             # First pass to define all the references
             self.regex_defns = re.compile(r'''
    -            \[\#(\w+)\s* # the counter.  Open square plus hash plus a word \1
    -            ([^@]*)\s*   # Some optional characters, that aren't an @. \2
    +            \[\#(\w+) # the counter.  Open square plus hash plus a word \1
    +            ([^@]*)   # Some optional characters, that aren't an @. \2
                 @(\w+)       # the id.  Should this be normed? \3
                 ([^\]]*)\]   # The rest of the text up to the terminating ] \4
                 ''', re.VERBOSE)
    @@ -908,7 +908,7 @@ def _do_numbering(self, text):
                 if len(match.groups()) != 4:
                     continue
                 counter = match.group(1)
    -            text_before = match.group(2)
    +            text_before = match.group(2).strip()
                 ref_id = match.group(3)
                 text_after = match.group(4)
                 number = counters.get(counter, 1)
    @@ -1926,9 +1926,9 @@ def _do_code_blocks(self, text):
     
         _fenced_code_block_re = re.compile(r'''
             (?:\n+|\A\n?)
    -        ^```\s*?([\w+-]+)?\s*?\n    # opening fence, $1 = optional lang
    -        (.*?)                       # $2 = code block content
    -        ^```[ \t]*\n                # closing fence
    +        ^```\s{0,99}([\w+-]+)?\s{0,99}\n  # opening fence, $1 = optional lang
    +        (.*?)                             # $2 = code block content
    +        ^```[ \t]*\n                      # closing fence
             ''', re.M | re.X | re.S)
     
         def _fenced_code_block_sub(self, match):
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

11

News mentions

0

No linked articles in our index yet.