python.lang.security.audit.regex-dos.regex_dos

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Detected usage of re.compile with an inefficient regular expression. This can lead to regular expression denial of service, which can result in service down time. Instead, check all regexes or use safer alternatives such as pyre2.

Run Locally

Run in CI

Defintion

rules:
  - id: regex_dos
    patterns:
      - pattern: |
          $A = re.compile("$B", ...)
          ...
          $A.$METHOD(...)
      - metavariable-analysis:
          analyzer: redos
          metavariable: $B
      - metavariable-regex:
          metavariable: $METHOD
          regex: (?!(escape)|(purge))
    message: Detected usage of re.compile with an inefficient regular expression.
      This can lead to regular expression denial of service, which can result in
      service down time. Instead, check all regexes or use safer alternatives
      such as pyre2.
    languages:
      - python
    severity: WARNING
    metadata:
      likelihood: LOW
      impact: MEDIUM
      confidence: LOW
      subcategory:
        - vuln
      owasp: A06:2017 - Security Misconfiguration
      cwe: "CWE-1333: Inefficient Regular Expression Complexity"
      category: security
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      technology:
        - python
      references:
        - https://docs.python.org/3/library/re.html
      vulnerability_class:
        - Denial-of-Service (DoS)

Examples

regex-dos.py

import re

redos = r"^(a+)+$"
regex = r"^[0-9]+$"

data = "foo"

# ruleid: regex_dos
pattern = re.compile(redos)
pattern.search(data)

# ok: regex_dos
pattern = re.compile(regex)
pattern.search(data)

# ruleid: regex_dos
pattern = re.compile(redos)
pattern.match(data)

# ok: regex_dos
pattern = re.compile(regex)
pattern.fullmatch(data)

# ok: regex_dos
pattern = re.compile(regex)
pattern.split(data)

# ruleid: regex_dos
pattern = re.compile(redos)
pattern.findall(data)

# ok: regex_dos
pattern.escape(redos)

# ok: regex_dos
pattern = re.compile(redos)
pattern.purge()