CVE-2024-28865 (published 2024-03-18T22:15Z)

django-wiki is a wiki system for Django. Installations of django-wiki prior to version 0.10.1 are vulnerable to maliciously crafted article content that can cause severe use of server CPU through a regular expression loop. Version 0.10.1 fixes this issue. As a workaround, close off access to create and edit articles by anonymous users.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/django-wiki/django-wiki
commit_details: repo_url: https://github.com/django-wiki/django-wiki
author: Benjamin Balder Bach
author_date: 2024-03-16 14:20:40+01:00
msg: Merge pull request from GHSA-wj85-w4f4-xh8h (#1350)

* ReDos: Apply `re.escape` to unsafe variable `keyword` before passing to `re.compile`

* Replace ReDos-vulnerable regex with the one from upstream Python-Markdown

* ReDos backtracking fix for macro plugin

* Add release note for GHSA-wj85-w4f4-xh8h

* Bump release date

* Bump version
repository: repo_url: https://github.com/django-wiki/django-wiki
repo_name: django-wiki/django-wiki
description: A wiki system with complex functionality for simple integration and a superb interface. Store your knowledge with style: Use django models.
repo_language: Python
owner: django-wiki
file_changes: filename: release_notes.rst
change_type: ModificationType.MODIFY
diff: @@ -68,6 +68,17 @@ Removed
 * Removes support for Python 3.7, 3.8, 3.9
 
 
+0.10.1
+------
+
+Released on 2024-03-16
+
+Security
+~~~~~~~~
+
+* Fixes reDOS issues: Denial of Service possible through unsafe regular expressions `GHSA-wj85-w4f4-xh8h <https://github.com/django-wiki/django-wiki/security/advisories/GHSA-wj85-w4f4-xh8h>`__ (Santos Gallegos, Benjamin Balder Bach)
+
+
 0.10
 ----
 

programming_language: Markdown
filename: codehilite.py
change_type: ModificationType.MODIFY
diff: @@ -1,3 +1,5 @@
+from textwrap import dedent
+
 import logging
 import re
 
@@ -7,6 +9,7 @@ from markdown.preprocessors import Preprocessor
 from markdown.treeprocessors import Treeprocessor
 from wiki.core.markdown import add_to_registry
 
+
 logger = logging.getLogger(__name__)
 
 
@@ -35,14 +38,17 @@ class WikiFencedBlockPreprocessor(Preprocessor):
     """
 
     FENCED_BLOCK_RE = re.compile(
-        r"""
-(?P<fence>^(?:~{3,}|`{3,}))[ ]*         # Opening ``` or ~~~
-(\{?\.?(?P<lang>[a-zA-Z0-9_+-]*))?[ ]*  # Optional {, and lang
-# Optional highlight lines, single- or double-quote-delimited
-(hl_lines=(?P<quot>"|')(?P<hl_lines>.*?)(?P=quot))?[ ]*
-}?[ ]*\n                                # Optional closing }
-(?P<code>.*?)(?<=\n)
-(?P=fence)[ ]*$""",
+        dedent(
+            r"""
+            (?P<fence>^(?:~{3,}|`{3,}))[ ]*                          # opening fence
+            ((\{(?P<attrs>[^\}\n]*)\})|                              # (optional {attrs} or
+            (\.?(?P<lang>[\w#.+-]*)[ ]*)?                            # optional (.)lang
+            (hl_lines=(?P<quot>"|')(?P<hl_lines>.*?)(?P=quot)[ ]*)?) # optional hl_lines)
+            \n                                                       # newline (end of opening fence)
+            (?P<code>.*?)(?<=\n)                                     # the code block
+            (?P=fence)[ ]*$                                          # closing fence
+        """
+        ),
         re.MULTILINE | re.DOTALL | re.VERBOSE,
     )
     CODE_WRAP = "<pre>%s</pre>"

programming_language: Python
filename: macro.py
change_type: ModificationType.MODIFY
diff: @@ -11,7 +11,11 @@ from wiki.plugins.macros.mdx import toc
 # http://stackoverflow.com/questions/430759/regex-for-managing-escaped-characters-for-items-like-string-literals
 re_sq_short = r"'([^'\\]*(?:\\.[^'\\]*)*)'"
 
-MACRO_RE = r"(\[(?P<macro>\w+)(?P<kwargs>\s\w+\:.+)*\])"
+
+MACRO_RE = (
+    r"""\[(?P<macro>\w+)(?P<kwargs>(\s+\w+\:([^\:\]\s]+|'[^']+'))+)*\]"""
+)
+
 KWARG_RE = re.compile(
     r"\s*(?P<arg>\w+)(:(?P<value>([^\']+|%s)))?" % re_sq_short, re.IGNORECASE
 )
@@ -48,10 +52,12 @@ class MacroPattern(markdown.inlinepatterns.Pattern):
         kwargs = m.group("kwargs")
         if not kwargs:
             return getattr(self, macro)()
+
         kwargs_dict = {}
         for kwarg in KWARG_RE.finditer(kwargs):
             arg = kwarg.group("arg")
             value = kwarg.group("value")
+
             if value is None:
                 value = True
             if isinstance(value, str):

programming_language: Python
filename: wiki_tags.py
change_type: ModificationType.MODIFY
diff: @@ -129,7 +129,7 @@ def get_content_snippet(content, keyword, max_words=30):
         before = " ".join(before_words)
         after = " ".join(after_words)
         html = ("%s %s %s" % (before, striptags(match), after)).strip()
-        kw_p = re.compile(r"(\S*%s\S*)" % keyword, re.IGNORECASE)
+        kw_p = re.compile(r"(\S*%s\S*)" % re.escape(keyword), re.IGNORECASE)
         html = kw_p.sub(r"<strong>\1</strong>", html)
 
         return mark_safe(html)

programming_language: Python
filename: test_toc.py
change_type: ModificationType.MODIFY
diff: @@ -8,6 +8,8 @@ from tests.base import TestBase
 
 
 class TocMacroTests(TestCase):
+    maxDiff = None
+
     def test_toc_renders_table_of_content(self):
         """Verifies that the [TOC] wiki code renders a Table of Content"""
         md = Markdown(extensions=["extra", WikiTocExtension()])

programming_language: Ruby