diff --git a/0001-fix-CVE-2020-13596.patch b/0001-fix-CVE-2020-13596.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4f6dde3323672756a8585b2c5e670708dff31d10
--- /dev/null
+++ b/0001-fix-CVE-2020-13596.patch
@@ -0,0 +1,85 @@
+From 6d61860b22875f358fac83d903dc629897934815 Mon Sep 17 00:00:00 2001
+From: Jon Dufresne <jon.dufresne@gmail.com>
+Date: Wed, 18 Sep 2024 20:37:30 +0800
+Subject: [PATCH] [2.0.x] Fixed CVE-2020-13596 -- Fixed potential XSS in admin
+ ForeignKeyRawIdWidget.
+
+---
+ django/contrib/admin/widgets.py | 2 +-
+ docs/releases/2.2.13.txt        | 8 ++++++++
+ tests/admin_widgets/models.py   | 6 ++++++
+ tests/admin_widgets/tests.py    | 9 +++++++++
+ 4 files changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
+index 3d11a40..40dba16 100644
+--- a/django/contrib/admin/widgets.py
++++ b/django/contrib/admin/widgets.py
+@@ -11,7 +11,7 @@ from django.core.validators import URLValidator
+ from django.db.models import CASCADE, UUIDField
+ from django.urls import reverse
+ from django.urls.exceptions import NoReverseMatch
+-from django.utils.html import smart_urlquote
++from django.utils.http import urlencode
+ from django.utils.http import urlencode
+ from django.utils.text import Truncator
+ from django.utils.translation import get_language
+diff --git a/docs/releases/2.2.13.txt b/docs/releases/2.2.13.txt
+index 3e455e7..d4a17d8 100644
+--- a/docs/releases/2.2.13.txt
++++ b/docs/releases/2.2.13.txt
+@@ -6,6 +6,14 @@ Django 2.2.13 release notes
+ 
+ Django 2.2.13 fixes two security issues and a regression in 2.2.12.
+ 
++CVE-2020-13596: Possible XSS via admin ``ForeignKeyRawIdWidget``
++================================================================
++
++Query parameters for the admin ``ForeignKeyRawIdWidget`` were not properly URL
++encoded, posing an XSS attack vector. ``ForeignKeyRawIdWidget`` now
++ensures query parameters are correctly URL encoded.
++
++
+ CVE-2020-13254: Potential data leakage via malformed memcached keys
+ ===================================================================
+ 
+diff --git a/tests/admin_widgets/models.py b/tests/admin_widgets/models.py
+index 0113ecb..093ff5a 100644
+--- a/tests/admin_widgets/models.py
++++ b/tests/admin_widgets/models.py
+@@ -29,6 +29,12 @@ class Member(models.Model):
+     def __str__(self):
+         return self.name
+ 
++class UnsafeLimitChoicesTo(models.Model):
++    band = models.ForeignKey(
++        Band,
++        models.CASCADE,
++        limit_choices_to={'name': '"&><escapeme'},
++    )
+ 
+ class Artist(models.Model):
+     pass
+diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py
+index 4281ed0..368e421 100644
+--- a/tests/admin_widgets/tests.py
++++ b/tests/admin_widgets/tests.py
+@@ -649,6 +649,15 @@ class AdminFileWidgetTests(TestDataMixin, TestCase):
+             html=True,
+         )
+ 
++    def test_render_unsafe_limit_choices_to(self):
++        rel = UnsafeLimitChoicesTo._meta.get_field('band').remote_field
++        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
++        self.assertHTMLEqual(
++            w.render('test', None),
++            '<input type="text" name="test" class="vForeignKeyRawIdAdminField">\n'
++            '<a href="/admin_widgets/band/?name=%22%26%3E%3Cescapeme&amp;_to_field=id" '
++            'class="related-lookup" id="lookup_id_test" title="Lookup"></a>'
++        )
+ 
+ @override_settings(ROOT_URLCONF="admin_widgets.urls")
+ class ForeignKeyRawIdWidgetTest(TestCase):
+-- 
+2.43.0
+
diff --git a/0002-fix-CVE-2024-45231.patch b/0002-fix-CVE-2024-45231.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a95699e113fc76b9c7d452ddb84ee51dc0623c21
--- /dev/null
+++ b/0002-fix-CVE-2024-45231.patch
@@ -0,0 +1,159 @@
+From bf4888d317ba4506d091eeac6e8b4f1fcc731199 Mon Sep 17 00:00:00 2001
+From: Natalia <124304+nessita@users.noreply.github.com>
+Date: Tue, 8 Oct 2024 18:15:00 +0800
+Subject: [PATCH] fix 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.
+
+
+---
+ django/contrib/auth/forms.py   |  9 ++++++++-
+ docs/ref/logging.txt           | 13 +++++++++++++
+ docs/releases/4.2.15.txt       | 12 ++++++++++++
+ docs/topics/auth/default.txt   |  4 +++-
+ tests/auth_tests/test_forms.py | 21 +++++++++++++++++++++
+ tests/mail/custombackend.py    |  4 ++++
+ 6 files changed, 61 insertions(+), 2 deletions(-)
+
+diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
+index 061dc81..7f85787 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):
+@@ -314,7 +316,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 b11fb75..dd089e6 100644
+--- a/docs/ref/logging.txt
++++ b/docs/ref/logging.txt
+@@ -204,6 +204,19 @@ all database queries.
+     Support for logging transaction management queries (``BEGIN``, ``COMMIT``,
+     and ``ROLLBACK``) was added.
+ 
++.. _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-security-logger:
+ 
+ ``django.security.*``
+diff --git a/docs/releases/4.2.15.txt b/docs/releases/4.2.15.txt
+index b1d4684..1b327d1 100644
+--- a/docs/releases/4.2.15.txt
++++ b/docs/releases/4.2.15.txt
+@@ -43,3 +43,15 @@ Bugfixes
+ * Fixed a regression in Django 4.2.14 that caused a crash in
+   ``LocaleMiddleware`` when processing a language code over 500 characters
+   (:ticket:`35627`).
++
++
++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 5289024..ad840c5 100644
+--- a/docs/topics/auth/default.txt
++++ b/docs/topics/auth/default.txt
+@@ -1661,7 +1661,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 81c56a4..d7470bc 100644
+--- a/tests/auth_tests/test_forms.py
++++ b/tests/auth_tests/test_forms.py
+@@ -560,6 +560,27 @@ class AuthenticationFormTest(TestDataMixin, TestCase):
+         self.assertTrue(form.is_valid())
+         self.assertEqual(form.non_field_errors(), [])
+ 
++    @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_username_field_max_length_matches_user_model(self):
+         self.assertEqual(CustomEmailField._meta.get_field("username").max_length, 255)
+diff --git a/tests/mail/custombackend.py b/tests/mail/custombackend.py
+index 14e7f07..50d6eb5 100644
+--- a/tests/mail/custombackend.py
++++ b/tests/mail/custombackend.py
+@@ -12,3 +12,7 @@ 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.spec b/python-django.spec
index ac31c22ebd5ede1bdfe9bf33ac003ebef19403a6..28914b159dd9767bf0a125f79e5451f9d4012988 100644
--- a/python-django.spec
+++ b/python-django.spec
@@ -1,12 +1,13 @@
 %global _empty_manifest_terminate_build 0
 Name:		python-django
 Version:	4.2.15
-Release:	1
+Release:	3
 Summary:	A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
 License:	Apache-2.0 and Python-2.0 and BSD-3-Clause
 URL:		https://www.djangoproject.com/
 Source0:        https://files.pythonhosted.org/packages/source/d/Django/Django-%{version}.tar.gz
-
+Patch0001:      0001-fix-CVE-2020-13596.patch
+Patch0002:      0002-fix-CVE-2024-45231.patch
 BuildArch:	noarch
 %description
 A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
@@ -72,6 +73,18 @@ mv %{buildroot}/doclist.lst .
 %{_docdir}/*
 
 %changelog
+* Wed Oct 09 2024 changtao <changtao@kylinos..cn> - 4.2.15-3
+- Type: bugfix
+- CVE: CVE-2024-45231
+- SUG: NA
+- DESC: Fix CVE-2024-45231
+
+* Thu Sep 19 2024 changtao <changtao@kylinos..cn> - 4.2.15-2
+- Type: bugfix
+- CVE: CVE-2020-13596
+- SUG: NA
+- DESC: Fix CVE-2020-13596
+
 * Thu Aug 08 2024 yaoxin <yao_xin001@hoperun.com> - 4.2.15-1
 - Update to 4.2.15
   * CVE-2024-41989: Memory exhaustion in ``django.utils.numberformat.floatformat()``