diff --git a/CVE-2022-34265.patch b/CVE-2022-34265.patch deleted file mode 100644 index 3d4f452e08f999e126286f2217083e5c68fc71fa..0000000000000000000000000000000000000000 --- a/CVE-2022-34265.patch +++ /dev/null @@ -1,109 +0,0 @@ -From a9010fe5555e6086a9d9ae50069579400ef0685e Mon Sep 17 00:00:00 2001 -From: Mariusz Felisiak -Date: Wed, 22 Jun 2022 12:44:04 +0200 -Subject: [PATCH] [3.2.x] Fixed CVE-2022-34265 -- Protected - Trunc(kind)/Extract(lookup_name) against SQL injection. - -Thanks Takuto Yoshikai (Aeye Security Lab) for the report. ---- - django/db/backends/base/operations.py | 3 ++ - django/db/models/functions/datetime.py | 4 +++ - docs/releases/3.2.14.txt | 11 ++++++ - .../datetime/test_extract_trunc.py | 34 +++++++++++++++++++ - 4 files changed, 52 insertions(+) - -diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py -index 0fcc607bcfb0..cdcd9885ba27 100644 ---- a/django/db/backends/base/operations.py -+++ b/django/db/backends/base/operations.py -@@ -9,6 +9,7 @@ - from django.db.backends import utils - from django.utils import timezone - from django.utils.encoding import force_str -+from django.utils.regex_helper import _lazy_re_compile - - - class BaseDatabaseOperations: -@@ -53,6 +54,8 @@ class BaseDatabaseOperations: - # Prefix for EXPLAIN queries, or None EXPLAIN isn't supported. - explain_prefix = None - -+ extract_trunc_lookup_pattern = _lazy_re_compile(r"[\w\-_()]+") -+ - def __init__(self, connection): - self.connection = connection - self._cache = None -diff --git a/django/db/models/functions/datetime.py b/django/db/models/functions/datetime.py -index 90e6f41be057..47651d281f19 100644 ---- a/django/db/models/functions/datetime.py -+++ b/django/db/models/functions/datetime.py -@@ -41,6 +41,8 @@ def __init__(self, expression, lookup_name=None, tzinfo=None, **extra): - super().__init__(expression, **extra) - - def as_sql(self, compiler, connection): -+ if not connection.ops.extract_trunc_lookup_pattern.fullmatch(self.lookup_name): -+ raise ValueError("Invalid lookup_name: %s" % self.lookup_name) - sql, params = compiler.compile(self.lhs) - lhs_output_field = self.lhs.output_field - if isinstance(lhs_output_field, DateTimeField): -@@ -192,6 +194,8 @@ def __init__(self, expression, output_field=None, tzinfo=None, is_dst=None, **ex - super().__init__(expression, output_field=output_field, **extra) - - def as_sql(self, compiler, connection): -+ if not connection.ops.extract_trunc_lookup_pattern.fullmatch(self.kind): -+ raise ValueError("Invalid kind: %s" % self.kind) - inner_sql, inner_params = compiler.compile(self.lhs) - tzname = None - if isinstance(self.lhs.output_field, DateTimeField): -diff --git a/tests/db_functions/datetime/test_extract_trunc.py b/tests/db_functions/datetime/test_extract_trunc.py -index 258600127f93..27ed3ae63ee5 100644 ---- a/tests/db_functions/datetime/test_extract_trunc.py -+++ b/tests/db_functions/datetime/test_extract_trunc.py -@@ -177,6 +177,23 @@ def test_extract_year_lessthan_lookup(self): - self.assertEqual(qs.count(), 1) - self.assertGreaterEqual(str(qs.query).lower().count('extract'), 2) - -+ def test_extract_lookup_name_sql_injection(self): -+ start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) -+ end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) -+ if settings.USE_TZ: -+ start_datetime = timezone.make_aware(start_datetime) -+ end_datetime = timezone.make_aware(end_datetime) -+ self.create_model(start_datetime, end_datetime) -+ self.create_model(end_datetime, start_datetime) -+ -+ msg = "Invalid lookup_name: " -+ with self.assertRaisesMessage(ValueError, msg): -+ DTModel.objects.filter( -+ start_datetime__year=Extract( -+ "start_datetime", "day' FROM start_datetime)) OR 1=1;--" -+ ) -+ ).exists() -+ - def test_extract_func(self): - start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) - end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) -@@ -620,6 +637,23 @@ def test_extract_second_func(self): - ) - self.assertEqual(DTModel.objects.filter(start_datetime__second=ExtractSecond('start_datetime')).count(), 2) - -+ def test_trunc_lookup_name_sql_injection(self): -+ start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) -+ end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) -+ if settings.USE_TZ: -+ start_datetime = timezone.make_aware(start_datetime) -+ end_datetime = timezone.make_aware(end_datetime) -+ self.create_model(start_datetime, end_datetime) -+ self.create_model(end_datetime, start_datetime) -+ msg = "Invalid kind: " -+ with self.assertRaisesMessage(ValueError, msg): -+ DTModel.objects.filter( -+ start_datetime__date=Trunc( -+ "start_datetime", -+ "year', start_datetime)) OR 1=1;--", -+ ) -+ ).exists() -+ - def test_trunc_func(self): - start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) - end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) diff --git a/3.2.12.tar.gz b/Django-3.2.16.tar.gz similarity index 54% rename from 3.2.12.tar.gz rename to Django-3.2.16.tar.gz index 6233704040e9580429c8f4a1a77a5311ed24db39..625f84d45754f8216440e309dc062905c61f05b7 100644 Binary files a/3.2.12.tar.gz and b/Django-3.2.16.tar.gz differ diff --git a/backport-CVE-2022-36359.patch b/backport-CVE-2022-36359.patch deleted file mode 100644 index 97dc3ff6ee85773ee3922c0a9caa77c368d95a43..0000000000000000000000000000000000000000 --- a/backport-CVE-2022-36359.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 8c5a1dfe34ea52cc2af21064a8654bfaa8b7a012 Mon Sep 17 00:00:00 2001 -From: Carlton Gibson -Date: Wed, 27 Jul 2022 10:27:42 +0200 -Subject: [PATCH] [3.2.x] Fixed CVE-2022-36359: Escaped filename in - Content-Disposition header. - -Thanks to Motoyasu Saburi for the report. ---- - django/http/response.py | 4 +++- - docs/releases/3.2.15.txt | 8 ++++++- - tests/responses/test_fileresponse.py | 35 ++++++++++++++++++++++++++++ - 3 files changed, 45 insertions(+), 2 deletions(-) - -diff --git a/django/http/response.py b/django/http/response.py -index 1c22edaff3..73f87d7bda 100644 ---- a/django/http/response.py -+++ b/django/http/response.py -@@ -485,7 +485,9 @@ class FileResponse(StreamingHttpResponse): - disposition = 'attachment' if self.as_attachment else 'inline' - try: - filename.encode('ascii') -- file_expr = 'filename="{}"'.format(filename) -+ file_expr = 'filename="{}"'.format( -+ filename.replace('\\', '\\\\').replace('"', r'\"') -+ ) - except UnicodeEncodeError: - file_expr = "filename*=utf-8''{}".format(quote(filename)) - self.headers['Content-Disposition'] = '{}; {}'.format(disposition, file_expr) -diff --git a/tests/responses/test_fileresponse.py b/tests/responses/test_fileresponse.py -index 46d407bdf5..b4ef82ef3e 100644 ---- a/tests/responses/test_fileresponse.py -+++ b/tests/responses/test_fileresponse.py -@@ -89,3 +89,38 @@ class FileResponseTests(SimpleTestCase): - response.headers['Content-Disposition'], - "attachment; filename*=utf-8''%E7%A5%9D%E6%82%A8%E5%B9%B3%E5%AE%89.odt" - ) -+ -+ def test_content_disposition_escaping(self): -+ # fmt: off -+ tests = [ -+ ( -+ 'multi-part-one";\" dummy".txt', -+ r"multi-part-one\";\" dummy\".txt" -+ ), -+ ] -+ # fmt: on -+ # Non-escape sequence backslashes are path segments on Windows, and are -+ # eliminated by an os.path.basename() check in FileResponse. -+ if sys.platform != "win32": -+ # fmt: off -+ tests += [ -+ ( -+ 'multi-part-one\\";\" dummy".txt', -+ r"multi-part-one\\\";\" dummy\".txt" -+ ), -+ ( -+ 'multi-part-one\\";\\\" dummy".txt', -+ r"multi-part-one\\\";\\\" dummy\".txt" -+ ) -+ ] -+ # fmt: on -+ for filename, escaped in tests: -+ with self.subTest(filename=filename, escaped=escaped): -+ response = FileResponse( -+ io.BytesIO(b"binary content"), filename=filename, as_attachment=True -+ ) -+ response.close() -+ self.assertEqual( -+ response.headers["Content-Disposition"], -+ f'attachment; filename="{escaped}"', -+ ) --- -2.36.1 - diff --git a/python-django.spec b/python-django.spec index 5abf8fd18e52610d3ec7e56483034ea72b7a6aef..8ecd92a3a7fcb0a218a1251a600529de0d99f6d1 100644 --- a/python-django.spec +++ b/python-django.spec @@ -1,14 +1,11 @@ %global _empty_manifest_terminate_build 0 Name: python-django -Version: 3.2.12 -Release: 3 +Version: 3.2.16 +Release: 1 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://github.com/django/django/archive/refs/tags/3.2.12.tar.gz -#https://github.com/django/django/commit/a9010fe5555e6086a9d9ae50069579400ef0685e -Patch0: CVE-2022-34265.patch -Patch1: backport-CVE-2022-36359.patch +Source0: https://files.pythonhosted.org/packages/f1/d7/8ddb9d8fbbffd33329cf6dfc33e8367a8969c05cf91bc63138ca116301ba/Django-%{version}.tar.gz BuildArch: noarch @@ -36,7 +33,7 @@ Provides: python3-Django-doc Development documents and examples for Django %prep -%autosetup -n django-%{version} -p1 +%autosetup -n Django-%{version} -p1 %build %py3_build @@ -76,6 +73,11 @@ mv %{buildroot}/doclist.lst . %{_docdir}/* %changelog +* Mon Apr 08 2024 OpenStack_SIG - 3.2.16-1 +- Upgrade package to version 3.2.16 +- Remove `CVE-2022-34265.patch` and `backport-CVE-2022-36359.patch`, as they are inclueded in 3.2.16 +- Major changes: bug and CVE fixes + * Tue Aug 09 2022 huangduirong - 3.2.12-3 - Type: bugfix - CVE: CVE-2022-36359