VYPR
High severityNVD Advisory· Published Oct 1, 2025· Updated Nov 4, 2025

CVE-2025-59681

CVE-2025-59681

Description

An issue was discovered in Django 4.2 before 4.2.25, 5.1 before 5.1.13, and 5.2 before 5.2.7. QuerySet.annotate(), QuerySet.alias(), QuerySet.aggregate(), and QuerySet.extra() are subject to SQL injection in column aliases, when using a suitably crafted dictionary, with dictionary expansion, as the **kwargs passed to these methods (on MySQL and MariaDB).

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
DjangoPyPI
>= 4.2, < 4.2.254.2.25
DjangoPyPI
>= 5.1, < 5.1.135.1.13
DjangoPyPI
>= 5.2, < 5.2.75.2.7

Affected products

1

Patches

2
43d84aef04a9

Added CVE-2025-59681 and CVE-2025-59682 to security archive.

https://github.com/django/djangoJacob WallsOct 1, 2025via ghsa
1 file changed · +24 0
  • docs/releases/security.txt+24 0 modified
    @@ -36,6 +36,30 @@ Issues under Django's security process
     All security issues have been handled under versions of Django's security
     process. These are listed below.
     
    +October 1, 2025 - :cve:`2025-59681`
    +-----------------------------------
    +
    +Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, ``aggregate()``, and ``extra()`` on MySQL and MariaDB.
    +`Full description
    +<https://www.djangoproject.com/weblog/2025/oct/01/security-releases/>`__
    +
    +* Django 6.0 :commit:`(patch) <4ceaaee7e04b416fc465e838a6ef43ca0ccffafe>`
    +* Django 5.2 :commit:`(patch) <52fbae0a4dbbe5faa59827f8f05694a0065cc135>`
    +* Django 5.1 :commit:`(patch) <01d2d770e22bffe53c7f1e611e2bbca94cb8a2e7>`
    +* Django 4.2 :commit:`(patch) <38d9ef8c7b5cb6ef51b933e51a20e0e0063f33d5>`
    +
    +October 1, 2025 - :cve:`2025-59682`
    +-----------------------------------
    +
    +Potential partial directory-traversal via ``archive.extract()``.
    +`Full description
    +<https://www.djangoproject.com/weblog/2025/oct/01/security-releases/>`__
    +
    +* Django 6.0 :commit:`(patch) <af067f56c1dd467df4abd0ddd409a700da1f03ba>`
    +* Django 5.2 :commit:`(patch) <ed8fc39d77465eddbde1191a054ae965f6a8a584>`
    +* Django 5.1 :commit:`(patch) <74fa85c688a87224637155902bcd738bb9e65e11>`
    +* Django 4.2 :commit:`(patch) <9504bbaa392c9fe37eee9291f5b4c29eb6037619>`
    +
     September 3, 2025 - :cve:`2025-57833`
     -------------------------------------
     
    
41b43c74bda1

Fixed CVE-2025-59681 -- Protected QuerySet.annotate(), alias(), aggregate(), and extra() against SQL injection in column aliases on MySQL/MariaDB.

https://github.com/django/djangoMariusz FelisiakSep 10, 2025via ghsa
8 files changed · +64 39
  • django/db/models/sql/query.py+9 8 modified
    @@ -51,12 +51,12 @@
     __all__ = ["Query", "RawQuery"]
     
     # RemovedInDjango70Warning: When the deprecation ends, replace with:
    -# Quotation marks ('"`[]), whitespace characters, semicolons, percent signs
    -# or inline SQL comments are forbidden in column aliases.
    -# FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|%|--|/\*|\*/")
    -# Quotation marks ('"`[]), whitespace characters, semicolons, or inline
    +# Quotation marks ('"`[]), whitespace characters, semicolons, percent signs,
    +# hashes, or inline SQL comments are forbidden in column aliases.
    +# FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|%|#|--|/\*|\*/")
    +# Quotation marks ('"`[]), whitespace characters, semicolons, hashes, or inline
     # SQL comments are forbidden in column aliases.
    -FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|--|/\*|\*/")
    +FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|#|--|/\*|\*/")
     
     # Inspired from
     # https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
    @@ -1222,11 +1222,12 @@ def check_alias(self, alias):
                 )
             if FORBIDDEN_ALIAS_PATTERN.search(alias):
                 raise ValueError(
    -                "Column aliases cannot contain whitespace characters, quotation marks, "
    +                "Column aliases cannot contain whitespace characters, hashes, "
                     # RemovedInDjango70Warning: When the deprecation ends, replace
                     # with:
    -                # "semicolons, percent signs, or SQL comments."
    -                "semicolons, or SQL comments."
    +                # "quotation marks, semicolons, percent signs, or SQL "
    +                # "comments."
    +                "quotation marks, semicolons, or SQL comments."
                 )
     
         def add_annotation(self, annotation, alias, select=True):
    
  • docs/releases/4.2.25.txt+8 1 modified
    @@ -7,4 +7,11 @@ Django 4.2.25 release notes
     Django 4.2.25 fixes one security issue with severity "high" and one security
     issue with severity "low" in 4.2.24.
     
    -...
    +CVE-2025-59681: Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, ``aggregate()``, and ``extra()`` on MySQL and MariaDB
    +======================================================================================================================================
    +
    +:meth:`.QuerySet.annotate`, :meth:`~.QuerySet.alias`,
    +:meth:`~.QuerySet.aggregate`, and :meth:`~.QuerySet.extra` methods were subject
    +to SQL injection in column aliases, using a suitably crafted dictionary, with
    +dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
    +:cve:`2022-28346`).
    
  • docs/releases/5.1.13.txt+8 1 modified
    @@ -7,4 +7,11 @@ Django 5.1.13 release notes
     Django 5.1.13 fixes one security issue with severity "high" and one security
     issue with severity "low" in 5.1.12.
     
    -...
    +CVE-2025-59681: Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, ``aggregate()``, and ``extra()`` on MySQL and MariaDB
    +======================================================================================================================================
    +
    +:meth:`.QuerySet.annotate`, :meth:`~.QuerySet.alias`,
    +:meth:`~.QuerySet.aggregate`, and :meth:`~.QuerySet.extra` methods were subject
    +to SQL injection in column aliases, using a suitably crafted dictionary, with
    +dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
    +:cve:`2022-28346`).
    
  • docs/releases/5.2.7.txt+9 0 modified
    @@ -8,6 +8,15 @@ Django 5.2.7 fixes one security issue with severity "high", one security issue
     with severity "low", and one bug in 5.2.6. Also, the latest string translations
     from Transifex are incorporated.
     
    +CVE-2025-59681: Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, ``aggregate()``, and ``extra()`` on MySQL and MariaDB
    +======================================================================================================================================
    +
    +:meth:`.QuerySet.annotate`, :meth:`~.QuerySet.alias`,
    +:meth:`~.QuerySet.aggregate`, and :meth:`~.QuerySet.extra` methods were subject
    +to SQL injection in column aliases, using a suitably crafted dictionary, with
    +dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
    +:cve:`2022-28346`).
    +
     Bugfixes
     ========
     
    
  • tests/aggregation/tests.py+2 2 modified
    @@ -2244,8 +2244,8 @@ def test_exists_none_with_aggregate(self):
         def test_alias_sql_injection(self):
             crafted_alias = """injected_name" from "aggregation_author"; --"""
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 Author.objects.aggregate(**{crafted_alias: Avg("age")})
    
  • tests/annotations/tests.py+22 21 modified
    @@ -1161,12 +1161,12 @@ def test_alias_sql_injection(self):
             crafted_alias = """injected_name" from "annotations_book"; --"""
             # RemovedInDjango70Warning: When the deprecation ends, replace with:
             # msg = (
    -        #    "Column aliases cannot contain whitespace characters, quotation "
    -        #    "marks, semicolons, percent signs, or SQL comments."
    +        #    "Column aliases cannot contain whitespace characters, hashes, "
    +        #    "quotation marks, semicolons, percent signs, or SQL comments."
             # )
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 Book.objects.annotate(**{crafted_alias: Value(1)})
    @@ -1175,12 +1175,12 @@ def test_alias_filtered_relation_sql_injection(self):
             crafted_alias = """injected_name" from "annotations_book"; --"""
             # RemovedInDjango70Warning: When the deprecation ends, replace with:
             # msg = (
    -        #    "Column aliases cannot contain whitespace characters, quotation "
    -        #    "marks, semicolons, percent signs, or SQL comments."
    +        #    "Column aliases cannot contain whitespace characters, hashes, "
    +        #    "quotation marks, semicolons, percent signs, or SQL comments."
             # )
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 Book.objects.annotate(**{crafted_alias: FilteredRelation("author")})
    @@ -1199,18 +1199,19 @@ def test_alias_forbidden_chars(self):
                 "alias;",
                 # RemovedInDjango70Warning: When the deprecation ends, add this:
                 # "alias%",
    -            # [] are used by MSSQL.
    +            # [] and # are used by MSSQL.
                 "alias[",
                 "alias]",
    +            "ali#as",
             ]
             # RemovedInDjango70Warning: When the deprecation ends, replace with:
             # msg = (
    -        #    "Column aliases cannot contain whitespace characters, quotation "
    -        #    "marks, semicolons, percent signs, or SQL comments."
    +        #    "Column aliases cannot contain whitespace characters, hashes, "
    +        #    "quotation marks, semicolons, percent signs, or SQL comments."
             # )
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             for crafted_alias in tests:
                 with self.subTest(crafted_alias):
    @@ -1516,12 +1517,12 @@ def test_alias_sql_injection(self):
             crafted_alias = """injected_name" from "annotations_book"; --"""
             # RemovedInDjango70Warning: When the deprecation ends, replace with:
             # msg = (
    -        #    "Column aliases cannot contain whitespace characters, quotation "
    -        #    "marks, semicolons, percent signs, or SQL comments."
    +        #    "Column aliases cannot contain whitespace characters, hashes, "
    +        #    "quotation marks, semicolons, percent signs, or SQL comments."
             # )
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 Book.objects.alias(**{crafted_alias: Value(1)})
    @@ -1530,12 +1531,12 @@ def test_alias_filtered_relation_sql_injection(self):
             crafted_alias = """injected_name" from "annotations_book"; --"""
             # RemovedInDjango70Warning: When the deprecation ends, replace with:
             # msg = (
    -        #    "Column aliases cannot contain whitespace characters, quotation "
    -        #    "marks, semicolons, percent signs, or SQL comments."
    +        #    "Column aliases cannot contain whitespace characters, hashes, "
    +        #    "quotation marks, semicolons, percent signs, or SQL comments."
             # )
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 Book.objects.alias(**{crafted_alias: FilteredRelation("authors")})
    
  • tests/expressions/test_queryset_values.py+4 4 modified
    @@ -44,8 +44,8 @@ def test_values_expression_containing_percent_sign_deprecation_warns_once(self):
         def test_values_expression_alias_sql_injection(self):
             crafted_alias = """injected_name" from "expressions_company"; --"""
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 Company.objects.values(**{crafted_alias: F("ceo__salary")})
    @@ -54,8 +54,8 @@ def test_values_expression_alias_sql_injection(self):
         def test_values_expression_alias_sql_injection_json_field(self):
             crafted_alias = """injected_name" from "expressions_company"; --"""
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 JSONFieldModel.objects.values(f"data__{crafted_alias}")
    
  • tests/queries/tests.py+2 2 modified
    @@ -1967,8 +1967,8 @@ def test_extra_select_literal_percent_s(self):
         def test_extra_select_alias_sql_injection(self):
             crafted_alias = """injected_name" from "queries_note"; --"""
             msg = (
    -            "Column aliases cannot contain whitespace characters, quotation marks, "
    -            "semicolons, or SQL comments."
    +            "Column aliases cannot contain whitespace characters, hashes, quotation "
    +            "marks, semicolons, or SQL comments."
             )
             with self.assertRaisesMessage(ValueError, msg):
                 Note.objects.extra(select={crafted_alias: "1"})
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

10

News mentions

0

No linked articles in our index yet.