From d240ef1baf641cf4c3945f9c1cb7b70bbe2808d0 Mon Sep 17 00:00:00 2001 From: bbrucezhang Date: Thu, 20 Feb 2025 11:38:45 +0800 Subject: [PATCH 1/4] Fix CVE-2024-56374 --- python-django-5.0.8-CVE-2024-45230.patch | 178 -------------------- python-django-5.0.8-CVE-2024-45231.patch | 199 ----------------------- python-django-5.0.8-CVE-2024-53907.patch | 88 ---------- python-django-5.0.8-CVE-2024-53908.patch | 145 ----------------- python-django.spec | 17 +- sources | 2 +- 6 files changed, 9 insertions(+), 620 deletions(-) delete mode 100644 python-django-5.0.8-CVE-2024-45230.patch delete mode 100644 python-django-5.0.8-CVE-2024-45231.patch delete mode 100644 python-django-5.0.8-CVE-2024-53907.patch delete mode 100644 python-django-5.0.8-CVE-2024-53908.patch diff --git a/python-django-5.0.8-CVE-2024-45230.patch b/python-django-5.0.8-CVE-2024-45230.patch deleted file mode 100644 index 6edf27a..0000000 --- a/python-django-5.0.8-CVE-2024-45230.patch +++ /dev/null @@ -1,178 +0,0 @@ -From 022ab0a75c76ab2ea31dfcc5f2cf5501e378d397 Mon Sep 17 00:00:00 2001 -From: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> -Date: Mon, 12 Aug 2024 15:17:57 +0200 -Subject: [PATCH] [5.1.x] Fixed CVE-2024-45230 -- Mitigated potential DoS in - urlize and urlizetrunc template filters. - -Thanks MProgrammer (https://hackerone.com/mprogrammer) for the report. ---- - django/utils/html.py | 17 ++++++++------ - docs/ref/templates/builtins.txt | 11 +++++++++ - docs/releases/4.2.16.txt | 14 +++++++++++ - docs/releases/5.0.9.txt | 14 +++++++++++ - docs/releases/5.1.1.txt | 13 +++++++++++ - .../filter_tests/test_urlize.py | 23 +++++++++++++++++++ - tests/utils_tests/test_html.py | 1 + - 7 files changed, 86 insertions(+), 7 deletions(-) - create mode 100644 docs/releases/4.2.16.txt - create mode 100644 docs/releases/5.0.9.txt - create mode 100644 docs/releases/5.1.1.txt - -diff --git a/django/utils/html.py b/django/utils/html.py -index 154c820..0719347 100644 ---- a/django/utils/html.py -+++ b/django/utils/html.py -@@ -427,14 +427,17 @@ class Urlizer: - potential_entity = middle[amp:] - escaped = html.unescape(potential_entity) - if escaped == potential_entity or escaped.endswith(";"): -- rstripped = middle.rstrip(";") -- amount_stripped = len(middle) - len(rstripped) -- if amp > -1 and amount_stripped > 1: -- # Leave a trailing semicolon as might be an entity. -- trail = middle[len(rstripped) + 1 :] + trail -- middle = rstripped + ";" -+ rstripped = middle.rstrip(self.trailing_punctuation_chars) -+ trail_start = len(rstripped) -+ amount_trailing_semicolons = len(middle) - len(middle.rstrip(";")) -+ if amp > -1 and amount_trailing_semicolons > 1: -+ # Leave up to most recent semicolon as might be an entity. -+ recent_semicolon = middle[trail_start:].index(";") -+ middle_semicolon_index = recent_semicolon + trail_start + 1 -+ trail = middle[middle_semicolon_index:] + trail -+ middle = rstripped + middle[trail_start:middle_semicolon_index] - else: -- trail = middle[len(rstripped) :] + trail -+ trail = middle[trail_start:] + trail - middle = rstripped - trimmed_something = True - -diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt -index 3e2d638..86841b3 100644 ---- a/docs/ref/templates/builtins.txt -+++ b/docs/ref/templates/builtins.txt -@@ -2932,6 +2932,17 @@ Django's built-in :tfilter:`escape` filter. The default value for - email addresses that contain single quotes (``'``), things won't work as - expected. Apply this filter only to plain text. - -+.. warning:: -+ -+ Using ``urlize`` or ``urlizetrunc`` can incur a performance penalty, which -+ can become severe when applied to user controlled values such as content -+ stored in a :class:`~django.db.models.TextField`. You can use -+ :tfilter:`truncatechars` to add a limit to such inputs: -+ -+ .. code-block:: html+django -+ -+ {{ value|truncatechars:500|urlize }} -+ - .. templatefilter:: urlizetrunc - - ``urlizetrunc`` -diff --git a/docs/releases/4.2.16.txt b/docs/releases/4.2.16.txt -new file mode 100644 -index 0000000..b624d5c ---- /dev/null -+++ b/docs/releases/4.2.16.txt -@@ -0,0 +1,14 @@ -+=========================== -+Django 4.2.16 release notes -+=========================== -+*September 3, 2024* -+Django 4.2.16 fixes one security issue with severity "moderate" and one -+security issue with severity "low" in 4.2.15. -+ -+... -+CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` -+=========================================================================================== -+ -+:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential -+denial-of-service attack via very large inputs with a specific sequence of -+characters. -diff --git a/docs/releases/5.0.9.txt b/docs/releases/5.0.9.txt -new file mode 100644 -index 0000000..3b372df ---- /dev/null -+++ b/docs/releases/5.0.9.txt -@@ -0,0 +1,14 @@ -+=========================== -+Django 5.0.9 release notes -+=========================== -+*September 3, 2024* -+Django 5.0.9 fixes one security issue with severity "moderate" and one security -+issue with severity "low" in 5.0.8. -+ -+... -+CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` -+=========================================================================================== -+ -+:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential -+denial-of-service attack via very large inputs with a specific sequence of -+characters. -diff --git a/docs/releases/5.1.1.txt b/docs/releases/5.1.1.txt -new file mode 100644 -index 0000000..6a2827c ---- /dev/null -+++ b/docs/releases/5.1.1.txt -@@ -0,0 +1,13 @@ -+========================== -+Django 5.1.1 release notes -+========================== -+*September 3, 2024* -+Django 5.1.1 fixes one security issue with severity "moderate", one security -+issue with severity "low", and several bugs in 5.1. -+ -+CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` -+=========================================================================================== -+ -+:tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential -+denial-of-service attack via very large inputs with a specific sequence of -+characters. -diff --git a/tests/template_tests/filter_tests/test_urlize.py b/tests/template_tests/filter_tests/test_urlize.py -index 8f84e62..14908cb 100644 ---- a/tests/template_tests/filter_tests/test_urlize.py -+++ b/tests/template_tests/filter_tests/test_urlize.py -@@ -305,6 +305,29 @@ class FunctionTests(SimpleTestCase): - "http://testing.com/example.,:;)"!", - ) - -+ def test_trailing_semicolon(self): -+ self.assertEqual( -+ urlize("http://example.com?x=&", autoescape=False), -+ '' -+ "http://example.com?x=&", -+ ) -+ self.assertEqual( -+ urlize("http://example.com?x=&;", autoescape=False), -+ '' -+ "http://example.com?x=&;", -+ ) -+ self.assertEqual( -+ urlize("http://example.com?x=&;;", autoescape=False), -+ '' -+ "http://example.com?x=&;;", -+ ) -+ -+ self.assertEqual( -+ urlize("http://example.com?x=&.;...;", autoescape=False), -+ '' -+ "http://example.com?x=&.;...;", -+ ) -+ - def test_brackets(self): - """ - #19070 - Check urlize handles brackets properly -diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py -index 82dbd58..035585e 100644 ---- a/tests/utils_tests/test_html.py -+++ b/tests/utils_tests/test_html.py -@@ -374,6 +374,7 @@ class TestUtilsHtml(SimpleTestCase): - "&:" + ";" * 100_000, - "&.;" * 100_000, - ".;" * 100_000, -+ "&" + ";:" * 100_000, - ) - for value in tests: - with self.subTest(value=value): --- -2.43.0 diff --git a/python-django-5.0.8-CVE-2024-45231.patch b/python-django-5.0.8-CVE-2024-45231.patch deleted file mode 100644 index 23b874f..0000000 --- a/python-django-5.0.8-CVE-2024-45231.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 3c733c78d6f8e50296d6e248968b6516c92a53ca Mon Sep 17 00:00:00 2001 -From: Natalia <124304+nessita@users.noreply.github.com> -Date: Mon, 19 Aug 2024 14:47:38 -0300 -Subject: [PATCH] [5.1.x] Fixed CVE-2024-45231 -- Avoided server error on - password reset when email sending fails. - -On successful submission of a password reset request, an email is sent -to the accounts known to the system. If sending this email fails (due to -email backend misconfiguration, service provider outage, network issues, -etc.), an attacker might exploit this by detecting which password reset -requests succeed and which ones generate a 500 error response. - -Thanks to Thibaut Spriet for the report, and to Mariusz Felisiak, Adam -Johnson, and Sarah Boyce for the reviews. ---- - django/contrib/auth/forms.py | 9 ++++++++- - docs/ref/logging.txt | 12 ++++++++++++ - docs/releases/4.2.16.txt | 11 +++++++++++ - docs/releases/5.0.9.txt | 11 +++++++++++ - docs/releases/5.1.1.txt | 11 +++++++++++ - docs/topics/auth/default.txt | 4 +++- - tests/auth_tests/test_forms.py | 21 +++++++++++++++++++++ - tests/mail/custombackend.py | 6 ++++++ - 8 files changed, 83 insertions(+), 2 deletions(-) - -diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py -index 31e96ff..689014b 100644 ---- a/django/contrib/auth/forms.py -+++ b/django/contrib/auth/forms.py -@@ -1,3 +1,4 @@ -+import logging - import unicodedata - - from django import forms -@@ -16,6 +17,7 @@ from django.utils.translation import gettext - from django.utils.translation import gettext_lazy as _ - - UserModel = get_user_model() -+logger = logging.getLogger("django.contrib.auth") - - - def _unicode_ci_compare(s1, s2): -@@ -393,7 +395,12 @@ class PasswordResetForm(forms.Form): - html_email = loader.render_to_string(html_email_template_name, context) - email_message.attach_alternative(html_email, "text/html") - -- email_message.send() -+ try: -+ email_message.send() -+ except Exception: -+ logger.exception( -+ "Failed to send password reset email to %s", context["user"].pk -+ ) - - def get_users(self, email): - """Given an email, return matching user(s) who should receive a reset. -diff --git a/docs/ref/logging.txt b/docs/ref/logging.txt -index 8a7e589..24ab5d9 100644 ---- a/docs/ref/logging.txt -+++ b/docs/ref/logging.txt -@@ -209,6 +209,18 @@ Django development server. This logger generates an ``INFO`` message upon - detecting a modification in a source code file and may produce ``WARNING`` - messages during filesystem inspection and event subscription processes. - -+.. _django-contrib-auth-logger: -+ -+``django.contrib.auth`` -+~~~~~~~~~~~~~~~~~~~~~~~ -+ -+.. versionadded:: 4.2.16 -+ -+Log messages related to :doc:`contrib/auth`, particularly ``ERROR`` messages -+are generated when a :class:`~django.contrib.auth.forms.PasswordResetForm` is -+successfully submitted but the password reset email cannot be delivered due to -+a mail sending exception. -+ - .. _django-contrib-gis-logger: - - ``django.contrib.gis`` -diff --git a/docs/releases/4.2.16.txt b/docs/releases/4.2.16.txt -index b624d5c..f0f82ba 100644 ---- a/docs/releases/4.2.16.txt -+++ b/docs/releases/4.2.16.txt -@@ -12,3 +12,14 @@ CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html - :tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential - denial-of-service attack via very large inputs with a specific sequence of - characters. -+ -+CVE-2024-45231: Potential user email enumeration via response status on password reset -+====================================================================================== -+ -+Due to unhandled email sending failures, the -+:class:`~django.contrib.auth.forms.PasswordResetForm` class allowed remote -+attackers to enumerate user emails by issuing password reset requests and -+observing the outcomes. -+ -+To mitigate this risk, exceptions occurring during password reset email sending -+are now handled and logged using the :ref:`django-contrib-auth-logger` logger. -diff --git a/docs/releases/5.0.9.txt b/docs/releases/5.0.9.txt -index 3b372df..3faa716 100644 ---- a/docs/releases/5.0.9.txt -+++ b/docs/releases/5.0.9.txt -@@ -12,3 +12,14 @@ CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html - :tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential - denial-of-service attack via very large inputs with a specific sequence of - characters. -+ -+CVE-2024-45231: Potential user email enumeration via response status on password reset -+====================================================================================== -+ -+Due to unhandled email sending failures, the -+:class:`~django.contrib.auth.forms.PasswordResetForm` class allowed remote -+attackers to enumerate user emails by issuing password reset requests and -+observing the outcomes. -+ -+To mitigate this risk, exceptions occurring during password reset email sending -+are now handled and logged using the :ref:`django-contrib-auth-logger` logger. -diff --git a/docs/releases/5.1.1.txt b/docs/releases/5.1.1.txt -index 6a2827c..d79a961 100644 ---- a/docs/releases/5.1.1.txt -+++ b/docs/releases/5.1.1.txt -@@ -11,3 +11,14 @@ CVE-2024-45230: Potential denial-of-service vulnerability in ``django.utils.html - :tfilter:`urlize` and :tfilter:`urlizetrunc` were subject to a potential - denial-of-service attack via very large inputs with a specific sequence of - characters. -+ -+CVE-2024-45231: Potential user email enumeration via response status on password reset -+====================================================================================== -+ -+Due to unhandled email sending failures, the -+:class:`~django.contrib.auth.forms.PasswordResetForm` class allowed remote -+attackers to enumerate user emails by issuing password reset requests and -+observing the outcomes. -+ -+To mitigate this risk, exceptions occurring during password reset email sending -+are now handled and logged using the :ref:`django-contrib-auth-logger` logger. -diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt -index 1d2ea81..7278dca 100644 ---- a/docs/topics/auth/default.txt -+++ b/docs/topics/auth/default.txt -@@ -1723,7 +1723,9 @@ provides several built-in forms located in :mod:`django.contrib.auth.forms`: - .. method:: send_mail(subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None) - - Uses the arguments to send an ``EmailMultiAlternatives``. -- Can be overridden to customize how the email is sent to the user. -+ Can be overridden to customize how the email is sent to the user. If -+ you choose to override this method, be mindful of handling potential -+ exceptions raised due to email sending failures. - - :param subject_template_name: the template for the subject. - :param email_template_name: the template for the email body. -diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py -index 3dd9324..f1e8fb9 100644 ---- a/tests/auth_tests/test_forms.py -+++ b/tests/auth_tests/test_forms.py -@@ -1369,6 +1369,27 @@ class PasswordResetFormTest(TestDataMixin, TestCase): - ) - ) - -+ @override_settings(EMAIL_BACKEND="mail.custombackend.FailingEmailBackend") -+ def test_save_send_email_exceptions_are_catched_and_logged(self): -+ (user, username, email) = self.create_dummy_user() -+ form = PasswordResetForm({"email": email}) -+ self.assertTrue(form.is_valid()) -+ -+ with self.assertLogs("django.contrib.auth", level=0) as cm: -+ form.save() -+ -+ self.assertEqual(len(mail.outbox), 0) -+ self.assertEqual(len(cm.output), 1) -+ errors = cm.output[0].split("\n") -+ pk = user.pk -+ self.assertEqual( -+ errors[0], -+ f"ERROR:django.contrib.auth:Failed to send password reset email to {pk}", -+ ) -+ self.assertEqual( -+ errors[-1], "ValueError: FailingEmailBackend is doomed to fail." -+ ) -+ - @override_settings(AUTH_USER_MODEL="auth_tests.CustomEmailField") - def test_custom_email_field(self): - email = "test@mail.com" -diff --git a/tests/mail/custombackend.py b/tests/mail/custombackend.py -index 14e7f07..c63f1c0 100644 ---- a/tests/mail/custombackend.py -+++ b/tests/mail/custombackend.py -@@ -12,3 +12,9 @@ class EmailBackend(BaseEmailBackend): - # Messages are stored in an instance variable for testing. - self.test_outbox.extend(email_messages) - return len(email_messages) -+ -+ -+class FailingEmailBackend(BaseEmailBackend): -+ -+ def send_messages(self, email_messages): -+ raise ValueError("FailingEmailBackend is doomed to fail.") --- -2.43.0 diff --git a/python-django-5.0.8-CVE-2024-53907.patch b/python-django-5.0.8-CVE-2024-53907.patch deleted file mode 100644 index 9bde505..0000000 --- a/python-django-5.0.8-CVE-2024-53907.patch +++ /dev/null @@ -1,88 +0,0 @@ -From bbc74a7f7eb7335e913bdb4787f22e83a9be947e Mon Sep 17 00:00:00 2001 -From: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> -Date: Wed, 13 Nov 2024 15:06:23 +0100 -Subject: [PATCH] [5.1.x] Fixed CVE-2024-53907 -- Mitigated potential DoS in - strip_tags(). - -Origin: https://github.com/django/django/commit/bbc74a7f7eb7335e913bdb4787f22e83a9be947e - -Thanks to jiangniao for the report, and Shai Berger and Natalia Bidart -for the reviews. ---- - django/utils/html.py | 10 ++++++++-- - tests/utils_tests/test_html.py | 7 +++++++ - 5 files changed, 63 insertions(+), 2 deletions(-) - -diff --git a/django/utils/html.py b/django/utils/html.py -index d9513fc75848..ff8684f5a974 100644 ---- a/django/utils/html.py -+++ b/django/utils/html.py -@@ -7,6 +7,7 @@ - from html.parser import HTMLParser - from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit - -+from django.core.exceptions import SuspiciousOperation - from django.utils.deprecation import RemovedInDjango60Warning - from django.utils.encoding import punycode - from django.utils.functional import Promise, cached_property, keep_lazy, keep_lazy_text -@@ -37,6 +38,7 @@ - } - - MAX_URL_LENGTH = 2048 -+MAX_STRIP_TAGS_DEPTH = 50 - - - @keep_lazy(SafeString) -@@ -205,15 +207,19 @@ def _strip_once(value): - @keep_lazy_text - def strip_tags(value): - """Return the given HTML with all tags stripped.""" -- # Note: in typical case this loop executes _strip_once once. Loop condition -- # is redundant, but helps to reduce number of executions of _strip_once. - value = str(value) -+ # Note: in typical case this loop executes _strip_once twice (the second -+ # execution does not remove any more tags). -+ strip_tags_depth = 0 - while "<" in value and ">" in value: -+ if strip_tags_depth >= MAX_STRIP_TAGS_DEPTH: -+ raise SuspiciousOperation - new_value = _strip_once(value) - if value.count("<") == new_value.count("<"): - # _strip_once wasn't able to detect more tags. - break - value = new_value -+ strip_tags_depth += 1 - return value - - -diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py -index 9bee483dc7ff..75873061de41 100644 ---- a/tests/utils_tests/test_html.py -+++ b/tests/utils_tests/test_html.py -@@ -1,6 +1,7 @@ - import os - from datetime import datetime - -+from django.core.exceptions import SuspiciousOperation - from django.core.serializers.json import DjangoJSONEncoder - from django.test import SimpleTestCase - from django.utils.deprecation import RemovedInDjango60Warning -@@ -123,12 +124,18 @@ def test_strip_tags(self): - ("&h", "alert()h"), - (">br>br>br>X", "XX"), -+ ("<" * 50 + "a>" * 50, ""), - ) - for value, output in items: - with self.subTest(value=value, output=output): - self.check_output(strip_tags, value, output) - self.check_output(strip_tags, lazystr(value), output) - -+ def test_strip_tags_suspicious_operation(self): -+ value = "<" * 51 + "a>" * 51, "" -+ with self.assertRaises(SuspiciousOperation): -+ strip_tags(value) -+ - def test_strip_tags_files(self): - # Test with more lengthy content (also catching performance regressions) - for filename in ("strip_tags1.html", "strip_tags2.txt"): diff --git a/python-django-5.0.8-CVE-2024-53908.patch b/python-django-5.0.8-CVE-2024-53908.patch deleted file mode 100644 index 684df2a..0000000 --- a/python-django-5.0.8-CVE-2024-53908.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 6943d61818e63e77b65d8b1ae65941e8f04bd87b Mon Sep 17 00:00:00 2001 -From: Simon Charette -Date: Fri, 8 Nov 2024 21:27:31 -0500 -Subject: [PATCH] [5.1.x] Fixed CVE-2024-53908 -- Prevented SQL injections in - direct HasKeyLookup usage on Oracle. - -Origin: https://github.com/django/django/commit/6943d61818e63e77b65d8b1ae65941e8f04bd87b - -Thanks Seokchan Yoon for the report, and Mariusz Felisiak and Sarah -Boyce for the reviews. ---- - django/db/models/fields/json.py | 53 ++++++++++++++++++---------- - tests/model_fields/test_jsonfield.py | 9 +++++ - 5 files changed, 71 insertions(+), 18 deletions(-) - -diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py -index 1b219e620c9a..608da6036f87 100644 ---- a/django/db/models/fields/json.py -+++ b/django/db/models/fields/json.py -@@ -193,20 +193,18 @@ def compile_json_path_final_key(self, key_transform): - # Compile the final key without interpreting ints as array elements. - return ".%s" % json.dumps(key_transform) - -- def as_sql(self, compiler, connection, template=None): -+ def _as_sql_parts(self, compiler, connection): - # Process JSON path from the left-hand side. - if isinstance(self.lhs, KeyTransform): -- lhs, lhs_params, lhs_key_transforms = self.lhs.preprocess_lhs( -+ lhs_sql, lhs_params, lhs_key_transforms = self.lhs.preprocess_lhs( - compiler, connection - ) - lhs_json_path = compile_json_path(lhs_key_transforms) - else: -- lhs, lhs_params = self.process_lhs(compiler, connection) -+ lhs_sql, lhs_params = self.process_lhs(compiler, connection) - lhs_json_path = "$" -- sql = template % lhs - # Process JSON path from the right-hand side. - rhs = self.rhs -- rhs_params = [] - if not isinstance(rhs, (list, tuple)): - rhs = [rhs] - for key in rhs: -@@ -217,24 +215,43 @@ def as_sql(self, compiler, connection, template=None): - *rhs_key_transforms, final_key = rhs_key_transforms - rhs_json_path = compile_json_path(rhs_key_transforms, include_root=False) - rhs_json_path += self.compile_json_path_final_key(final_key) -- rhs_params.append(lhs_json_path + rhs_json_path) -+ yield lhs_sql, lhs_params, lhs_json_path + rhs_json_path -+ -+ def _combine_sql_parts(self, parts): - # Add condition for each key. - if self.logical_operator: -- sql = "(%s)" % self.logical_operator.join([sql] * len(rhs_params)) -- return sql, tuple(lhs_params) + tuple(rhs_params) -+ return "(%s)" % self.logical_operator.join(parts) -+ return "".join(parts) -+ -+ def as_sql(self, compiler, connection, template=None): -+ sql_parts = [] -+ params = [] -+ for lhs_sql, lhs_params, rhs_json_path in self._as_sql_parts( -+ compiler, connection -+ ): -+ sql_parts.append(template % (lhs_sql, "%s")) -+ params.extend(lhs_params + [rhs_json_path]) -+ return self._combine_sql_parts(sql_parts), tuple(params) - - def as_mysql(self, compiler, connection): - return self.as_sql( -- compiler, connection, template="JSON_CONTAINS_PATH(%s, 'one', %%s)" -+ compiler, connection, template="JSON_CONTAINS_PATH(%s, 'one', %s)" - ) - - def as_oracle(self, compiler, connection): -- sql, params = self.as_sql( -- compiler, connection, template="JSON_EXISTS(%s, '%%s')" -- ) -- # Add paths directly into SQL because path expressions cannot be passed -- # as bind variables on Oracle. -- return sql % tuple(params), [] -+ template = "JSON_EXISTS(%s, '%s')" -+ sql_parts = [] -+ params = [] -+ for lhs_sql, lhs_params, rhs_json_path in self._as_sql_parts( -+ compiler, connection -+ ): -+ # Add right-hand-side directly into SQL because it cannot be passed -+ # as bind variables to JSON_EXISTS. It might result in invalid -+ # queries but it is assumed that it cannot be evaded because the -+ # path is JSON serialized. -+ sql_parts.append(template % (lhs_sql, rhs_json_path)) -+ params.extend(lhs_params) -+ return self._combine_sql_parts(sql_parts), tuple(params) - - def as_postgresql(self, compiler, connection): - if isinstance(self.rhs, KeyTransform): -@@ -246,7 +263,7 @@ def as_postgresql(self, compiler, connection): - - def as_sqlite(self, compiler, connection): - return self.as_sql( -- compiler, connection, template="JSON_TYPE(%s, %%s) IS NOT NULL" -+ compiler, connection, template="JSON_TYPE(%s, %s) IS NOT NULL" - ) - - -@@ -455,9 +472,9 @@ def as_oracle(self, compiler, connection): - return "(NOT %s OR %s IS NULL)" % (sql, lhs), tuple(params) + tuple(lhs_params) - - def as_sqlite(self, compiler, connection): -- template = "JSON_TYPE(%s, %%s) IS NULL" -+ template = "JSON_TYPE(%s, %s) IS NULL" - if not self.rhs: -- template = "JSON_TYPE(%s, %%s) IS NOT NULL" -+ template = "JSON_TYPE(%s, %s) IS NOT NULL" - return HasKeyOrArrayIndex(self.lhs.lhs, self.lhs.key_name).as_sql( - compiler, - connection, -diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py -index ff42b1a14c38..e517ef682675 100644 ---- a/tests/model_fields/test_jsonfield.py -+++ b/tests/model_fields/test_jsonfield.py -@@ -29,6 +29,7 @@ - from django.db.models.expressions import RawSQL - from django.db.models.fields.json import ( - KT, -+ HasKey, - KeyTextTransform, - KeyTransform, - KeyTransformFactory, -@@ -582,6 +583,14 @@ def test_has_key_deep(self): - [expected], - ) - -+ def test_has_key_literal_lookup(self): -+ self.assertSequenceEqual( -+ NullableJSONModel.objects.filter( -+ HasKey(Value({"foo": "bar"}, JSONField()), "foo") -+ ).order_by("id"), -+ self.objs, -+ ) -+ - def test_has_key_list(self): - obj = NullableJSONModel.objects.create(value=[{"a": 1}, {"b": "x"}]) - tests = [ diff --git a/python-django.spec b/python-django.spec index bd9040d..0082a4c 100644 --- a/python-django.spec +++ b/python-django.spec @@ -3,16 +3,11 @@ Summary: A high-level Python Web framework Name: python-django -Version: 5.0.8 -Release: 3%{?dist} +Version: 5.1.5 +Release: 1%{?dist} License: BSD URL: https://www.djangoproject.com/ -Source0: https://github.com/django/django/archive/refs/tags/%{version}.tar.gz - -Patch001: python-django-5.0.8-CVE-2024-45230.patch -Patch002: python-django-5.0.8-CVE-2024-45231.patch -Patch003: python-django-5.0.8-CVE-2024-53907.patch -Patch004: python-django-5.0.8-CVE-2024-53908.patch +Source0: https://files.pythonhosted.org/packages/source/d/Django/Django-%{version}.tar.gz BuildArch: noarch @@ -48,7 +43,7 @@ Python Web framework. %package -n python3-django Summary: A high-level Python Web framework -BuildRequires: python3-devel python3-setuptools python3-pytz python3-sqlparse python-selenium python3-sphinx +BuildRequires: python3-devel python3-setuptools python3-pytz python3-sqlparse python-selenium python3-sphinx python3-pip python3-wheel BuildRequires: /usr/bin/pathfix.py python3-asgiref Requires: python3-pytz python3-sqlparse python3-argon2-cffi python3-bcrypt Provides: python-Django, python3-django @@ -122,6 +117,10 @@ python3 runtests.py --settings=test_sqlite --verbosity=2 --parallel 1 %changelog +* Thu Feb 20 2025 bbrucezhang - 5.1.5-1 +- [Type] security +- [DESC] Fix CVE-2024-56374 + * Thu Dec 12 2024 Shop You - 5.0.8-3 - [Type] security - [DESC] Resolves: CVE-2024-45230 CVE-2024-45231 CVE-2024-53908 CVE-2024-53907 diff --git a/sources b/sources index d29b767..32e6322 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (5.0.8.tar.gz) = 8f029108311cc96044fa160232551203d2dea2a9cab8673277fde6ad7c279061570b2dd46b4ba77f432bbda63074e5a413e07cd4c3d12a5c38d4b199b03198cf +SHA512 (Django-5.1.5.tar.gz) = cc28eb7166d9babdb3f3d61cc87eb9ed038d7115bd7de7da5b9cff33da114c334fd51140d32c597229cd07e400520bc92ebf69611c6a455ac926f3e9eaa5ee88 -- Gitee From 65523d269d8d2ad08f5aedb085556cb98d4935d1 Mon Sep 17 00:00:00 2001 From: bbrucezhang Date: Thu, 20 Feb 2025 14:22:21 +0800 Subject: [PATCH 2/4] fix build error --- python-django.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-django.spec b/python-django.spec index 0082a4c..dacda3f 100644 --- a/python-django.spec +++ b/python-django.spec @@ -56,7 +56,7 @@ without needing to reinvent the wheel. It’s free and open source. %prep -%autosetup -n django-%{version} -p1 +%autosetup -n Django-%{version} -p1 pathfix.py -pni "%{__python3} %{py3_shbang_opts}" . -- Gitee From 51a82b663b3bdd2671675c6747233033697433a6 Mon Sep 17 00:00:00 2001 From: bbrucezhang Date: Thu, 13 Mar 2025 17:40:14 +0800 Subject: [PATCH 3/4] fix build error --- python-django.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python-django.spec b/python-django.spec index dacda3f..c67ff92 100644 --- a/python-django.spec +++ b/python-django.spec @@ -61,11 +61,11 @@ without needing to reinvent the wheel. It’s free and open source. pathfix.py -pni "%{__python3} %{py3_shbang_opts}" . %build -%py3_build +%pyproject_wheel %install -%py3_install +%pyproject_install pathfix.py -pni "%{__python3} %{py3_shbang_opts}" %{buildroot}/usr/lib/python%{python3_version}/site-packages/django/conf/project_template/manage.py-tpl %if %{with doc} @@ -92,7 +92,7 @@ ln -s ./django-admin %{buildroot}%{_bindir}/python3-django-admin find %{buildroot} -name "*.po" -delete %check -cd %{_builddir}/django-%{version} +cd %{_builddir}/Django-%{version} export PYTHONPATH="$(pwd):%{?with_python_bootstrap:$PYTHONPATH}" cd tests python3 runtests.py --settings=test_sqlite --verbosity=2 --parallel 1 -- Gitee From 738053b58ce951251e8718c392e564cbf3e88bec Mon Sep 17 00:00:00 2001 From: bbrucezhang Date: Thu, 5 Jun 2025 17:40:55 +0800 Subject: [PATCH 4/4] Update to 5.2.2, Fix CVE-2025-26699 --- python-django.spec | 12 ++++++++---- sources | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/python-django.spec b/python-django.spec index c67ff92..4f535b4 100644 --- a/python-django.spec +++ b/python-django.spec @@ -3,11 +3,11 @@ Summary: A high-level Python Web framework Name: python-django -Version: 5.1.5 +Version: 5.2.2 Release: 1%{?dist} License: BSD URL: https://www.djangoproject.com/ -Source0: https://files.pythonhosted.org/packages/source/d/Django/Django-%{version}.tar.gz +Source0: https://files.pythonhosted.org/packages/source/d/django/django-%{version}.tar.gz BuildArch: noarch @@ -56,7 +56,7 @@ without needing to reinvent the wheel. It’s free and open source. %prep -%autosetup -n Django-%{version} -p1 +%autosetup -n django-%{version} -p1 pathfix.py -pni "%{__python3} %{py3_shbang_opts}" . @@ -92,7 +92,7 @@ ln -s ./django-admin %{buildroot}%{_bindir}/python3-django-admin find %{buildroot} -name "*.po" -delete %check -cd %{_builddir}/Django-%{version} +cd %{_builddir}/django-%{version} export PYTHONPATH="$(pwd):%{?with_python_bootstrap:$PYTHONPATH}" cd tests python3 runtests.py --settings=test_sqlite --verbosity=2 --parallel 1 @@ -117,6 +117,10 @@ python3 runtests.py --settings=test_sqlite --verbosity=2 --parallel 1 %changelog +* Thu Jun 5 2025 bbrucezhang - 5.2.2-1 +- [Type] security +- [DESC] Update to 5.2.2, Fix CVE-2025-26699 + * Thu Feb 20 2025 bbrucezhang - 5.1.5-1 - [Type] security - [DESC] Fix CVE-2024-56374 diff --git a/sources b/sources index 32e6322..ddd931a 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Django-5.1.5.tar.gz) = cc28eb7166d9babdb3f3d61cc87eb9ed038d7115bd7de7da5b9cff33da114c334fd51140d32c597229cd07e400520bc92ebf69611c6a455ac926f3e9eaa5ee88 +SHA512 (django-5.2.2.tar.gz) = b4d5be87bd0daf68df76e2f79781b72dc7cbe372148edd83aa1ab9ffbbda8785ee85e63309a06ea454d233ce23972ae51213680dcdd9824177cef8c3285ec439 -- Gitee