1
0
mirror of https://github.com/django/django.git synced 2025-03-31 03:30:46 +00:00

[4.2.x] Fixed CVE-2025-26699 -- Mitigated potential DoS in wordwrap template filter.

Thanks sw0rd1ight for the report.

Backport of 55d89e25f4115c5674cdd9b9bcba2bb2bb6d820b from main.
This commit is contained in:
Sarah Boyce 2025-02-25 09:40:54 +01:00
parent 348e46a3e0
commit e88f7376fe
3 changed files with 27 additions and 18 deletions

View File

@ -1,6 +1,7 @@
import gzip import gzip
import re import re
import secrets import secrets
import textwrap
import unicodedata import unicodedata
from gzip import GzipFile from gzip import GzipFile
from gzip import compress as gzip_compress from gzip import compress as gzip_compress
@ -97,24 +98,15 @@ def wrap(text, width):
``width``. ``width``.
""" """
def _generator(): wrapper = textwrap.TextWrapper(
for line in text.splitlines(True): # True keeps trailing linebreaks width=width,
max_width = min((line.endswith("\n") and width + 1 or width), width) break_long_words=False,
while len(line) > max_width: break_on_hyphens=False,
space = line[: max_width + 1].rfind(" ") + 1 )
if space == 0: result = []
space = line.find(" ") + 1 for line in text.splitlines(True):
if space == 0: result.extend(wrapper.wrap(line))
yield line return "\n".join(result)
line = ""
break
yield "%s\n" % line[: space - 1]
line = line[space:]
max_width = min((line.endswith("\n") and width + 1 or width), width)
if line:
yield line
return "".join(_generator())
class Truncator(SimpleLazyObject): class Truncator(SimpleLazyObject):

View File

@ -5,3 +5,9 @@ Django 4.2.20 release notes
*March 6, 2025* *March 6, 2025*
Django 4.2.20 fixes a security issue with severity "moderate" in 4.2.19. Django 4.2.20 fixes a security issue with severity "moderate" in 4.2.19.
CVE-2025-26699: Potential denial-of-service vulnerability in ``django.utils.text.wrap()``
=========================================================================================
The ``wrap()`` and :tfilter:`wordwrap` template filter were subject to a
potential denial-of-service attack when used with very long strings.

View File

@ -78,3 +78,14 @@ class FunctionTests(SimpleTestCase):
"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\n" "this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\n"
"I'm afraid", "I'm afraid",
) )
def test_wrap_long_text(self):
long_text = (
"this is a long paragraph of text that really needs"
" to be wrapped I'm afraid " * 20_000
)
self.assertIn(
"this is a\nlong\nparagraph\nof text\nthat\nreally\nneeds to\nbe wrapped\n"
"I'm afraid",
wordwrap(long_text, 10),
)