티스토리 수익 글 보기

티스토리 수익 글 보기

[4.2.x] Fixed CVE-2025-59681 — Protected QuerySet.annotate(), alias(… · django/django@38d9ef8 · GitHub
Skip to content

Commit 38d9ef8

Browse files
felixxmjacobtylerwalls
authored andcommitted
[4.2.x] Fixed CVE-2025-59681 — Protected QuerySet.annotate(), alias(), aggregate(), and extra() against SQL injection in column aliases on MySQL/MariaDB.
Thanks sw0rd1ight for the report. Follow up to 93cae5c. Backport of 41b43c7 from main.
1 parent 7c7d2a4 commit 38d9ef8

File tree

6 files changed

+32
24
lines changed

6 files changed

+32
24
lines changed

django/db/models/sql/query.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@
4646

4747
__all__ = ["Query", "RawQuery"]
4848

49-
# Quotation marks ('"`[]), whitespace characters, semicolons, or inline
49+
# Quotation marks ('"`[]), whitespace characters, semicolons, hashes, or inline
5050
# SQL comments are forbidden in column aliases.
51-
FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|--|/\*|\*/")
51+
FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|#|--|/\*|\*/")
5252

5353
# Inspired from
5454
# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
@@ -1123,8 +1123,8 @@ def join_parent_model(self, opts, model, alias, seen):
11231123
def check_alias(self, alias):
11241124
if FORBIDDEN_ALIAS_PATTERN.search(alias):
11251125
raise ValueError(
1126-
"Column aliases cannot contain whitespace characters, quotation marks, "
1127-
"semicolons, or SQL comments."
1126+
"Column aliases cannot contain whitespace characters, hashes, "
1127+
"quotation marks, semicolons, or SQL comments."
11281128
)
11291129

11301130
def add_annotation(self, annotation, alias, select=True):

docs/releases/4.2.25.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@ Django 4.2.25 release notes
77
Django 4.2.25 fixes one security issue with severity "high" and one security
88
issue with severity "low" in 4.2.24.
99

10-
...
10+
CVE-2025-59681: Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, ``aggregate()``, and ``extra()`` on MySQL and MariaDB
11+
======================================================================================================================================
12+
13+
:meth:`.QuerySet.annotate`, :meth:`~.QuerySet.alias`,
14+
:meth:`~.QuerySet.aggregate`, and :meth:`~.QuerySet.extra` methods were subject
15+
to SQL injection in column aliases, using a suitably crafted dictionary, with
16+
dictionary expansion, as the ``**kwargs`` passed to these methods (follow up to
17+
:cve:`2022-28346`).

tests/aggregation/tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,8 +2090,8 @@ def test_exists_none_with_aggregate(self):
20902090
def test_alias_sql_injection(self):
20912091
crafted_alias = """injected_name" from "aggregation_author"; --"""
20922092
msg = (
2093-
"Column aliases cannot contain whitespace characters, quotation marks, "
2094-
"semicolons, or SQL comments."
2093+
"Column aliases cannot contain whitespace characters, hashes, quotation "
2094+
"marks, semicolons, or SQL comments."
20952095
)
20962096
with self.assertRaisesMessage(ValueError, msg):
20972097
Author.objects.aggregate(**{crafted_alias: Avg("age")})

tests/annotations/tests.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,17 +1116,17 @@ def test_annotation_aggregate_with_m2o(self):
11161116
def test_alias_sql_injection(self):
11171117
crafted_alias = """injected_name" from "annotations_book"; --"""
11181118
msg = (
1119-
"Column aliases cannot contain whitespace characters, quotation marks, "
1120-
"semicolons, or SQL comments."
1119+
"Column aliases cannot contain whitespace characters, hashes, quotation "
1120+
"marks, semicolons, or SQL comments."
11211121
)
11221122
with self.assertRaisesMessage(ValueError, msg):
11231123
Book.objects.annotate(**{crafted_alias: Value(1)})
11241124

11251125
def test_alias_filtered_relation_sql_injection(self):
11261126
crafted_alias = """injected_name" from "annotations_book"; --"""
11271127
msg = (
1128-
"Column aliases cannot contain whitespace characters, quotation marks, "
1129-
"semicolons, or SQL comments."
1128+
"Column aliases cannot contain whitespace characters, hashes, quotation "
1129+
"marks, semicolons, or SQL comments."
11301130
)
11311131
with self.assertRaisesMessage(ValueError, msg):
11321132
Book.objects.annotate(**{crafted_alias: FilteredRelation("author")})
@@ -1143,13 +1143,14 @@ def test_alias_forbidden_chars(self):
11431143
"ali/*as",
11441144
"alias*/",
11451145
"alias;",
1146-
# [] are used by MSSQL.
1146+
# [] and # are used by MSSQL.
11471147
"alias[",
11481148
"alias]",
1149+
"ali#as",
11491150
]
11501151
msg = (
1151-
"Column aliases cannot contain whitespace characters, quotation marks, "
1152-
"semicolons, or SQL comments."
1152+
"Column aliases cannot contain whitespace characters, hashes, quotation "
1153+
"marks, semicolons, or SQL comments."
11531154
)
11541155
for crafted_alias in tests:
11551156
with self.subTest(crafted_alias):
@@ -1428,17 +1429,17 @@ def test_values_alias(self):
14281429
def test_alias_sql_injection(self):
14291430
crafted_alias = """injected_name" from "annotations_book"; --"""
14301431
msg = (
1431-
"Column aliases cannot contain whitespace characters, quotation marks, "
1432-
"semicolons, or SQL comments."
1432+
"Column aliases cannot contain whitespace characters, hashes, quotation "
1433+
"marks, semicolons, or SQL comments."
14331434
)
14341435
with self.assertRaisesMessage(ValueError, msg):
14351436
Book.objects.alias(**{crafted_alias: Value(1)})
14361437

14371438
def test_alias_filtered_relation_sql_injection(self):
14381439
crafted_alias = """injected_name" from "annotations_book"; --"""
14391440
msg = (
1440-
"Column aliases cannot contain whitespace characters, quotation marks, "
1441-
"semicolons, or SQL comments."
1441+
"Column aliases cannot contain whitespace characters, hashes, quotation "
1442+
"marks, semicolons, or SQL comments."
14421443
)
14431444
with self.assertRaisesMessage(ValueError, msg):
14441445
Book.objects.alias(**{crafted_alias: FilteredRelation("authors")})

tests/expressions/test_queryset_values.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ def test_values_expression(self):
3737
def test_values_expression_alias_sql_injection(self):
3838
crafted_alias = """injected_name" from "expressions_company"; --"""
3939
msg = (
40-
"Column aliases cannot contain whitespace characters, quotation marks, "
41-
"semicolons, or SQL comments."
40+
"Column aliases cannot contain whitespace characters, hashes, quotation "
41+
"marks, semicolons, or SQL comments."
4242
)
4343
with self.assertRaisesMessage(ValueError, msg):
4444
Company.objects.values(**{crafted_alias: F("ceo__salary")})
@@ -47,8 +47,8 @@ def test_values_expression_alias_sql_injection(self):
4747
def test_values_expression_alias_sql_injection_json_field(self):
4848
crafted_alias = """injected_name" from "expressions_company"; --"""
4949
msg = (
50-
"Column aliases cannot contain whitespace characters, quotation marks, "
51-
"semicolons, or SQL comments."
50+
"Column aliases cannot contain whitespace characters, hashes, quotation "
51+
"marks, semicolons, or SQL comments."
5252
)
5353
with self.assertRaisesMessage(ValueError, msg):
5454
JSONFieldModel.objects.values(f"data__{crafted_alias}")

tests/queries/tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,8 +1943,8 @@ def test_extra_select_literal_percent_s(self):
19431943
def test_extra_select_alias_sql_injection(self):
19441944
crafted_alias = """injected_name" from "queries_note"; --"""
19451945
msg = (
1946-
"Column aliases cannot contain whitespace characters, quotation marks, "
1947-
"semicolons, or SQL comments."
1946+
"Column aliases cannot contain whitespace characters, hashes, quotation "
1947+
"marks, semicolons, or SQL comments."
19481948
)
19491949
with self.assertRaisesMessage(ValueError, msg):
19501950
Note.objects.extra(select={crafted_alias: "1"})

0 commit comments

Comments
 (0)