Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9c6a5bd

Browse files
jacobtylerwallsnessita
authored andcommitted
[5.1.x] Fixed CVE-2025-13372 -- Protected FilteredRelation against SQL injection in column aliases on PostgreSQL.
Follow-up to CVE-2025-57833. Thanks Stackered for the report, and Simon Charette and Mariusz Felisiak for the reviews. Backport of 5b90ca1 from main.
1 parent e419ad8 commit 9c6a5bd

5 files changed

Lines changed: 53 additions & 0 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from django.db.models.sql.compiler import ( # isort:skip
2+
SQLAggregateCompiler,
3+
SQLCompiler as BaseSQLCompiler,
4+
SQLDeleteCompiler,
5+
SQLInsertCompiler,
6+
SQLUpdateCompiler,
7+
)
8+
9+
__all__ = [
10+
"SQLAggregateCompiler",
11+
"SQLCompiler",
12+
"SQLDeleteCompiler",
13+
"SQLInsertCompiler",
14+
"SQLUpdateCompiler",
15+
]
16+
17+
18+
class SQLCompiler(BaseSQLCompiler):
19+
def quote_name_unless_alias(self, name):
20+
if "$" in name:
21+
raise ValueError(
22+
"Dollar signs are not permitted in column aliases on PostgreSQL."
23+
)
24+
return super().quote_name_unless_alias(name)

django/db/backends/postgresql/operations.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def get_json_dumps(encoder):
2424

2525

2626
class DatabaseOperations(BaseDatabaseOperations):
27+
compiler_module = "django.db.backends.postgresql.compiler"
2728
cast_char_field_without_max_length = "varchar"
2829
explain_prefix = "EXPLAIN"
2930
explain_options = frozenset(

docs/releases/4.2.27.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ Django 4.2.27 release notes
77
Django 4.2.27 fixes one security issue with severity "high", one security issue
88
with severity "moderate", and one bug in 4.2.26.
99

10+
CVE-2025-13372: Potential SQL injection in ``FilteredRelation`` column aliases on PostgreSQL
11+
============================================================================================
12+
13+
:class:`.FilteredRelation` was subject to SQL injection in column aliases,
14+
using a suitably crafted dictionary, with dictionary expansion, as the
15+
``**kwargs`` passed to :meth:`.QuerySet.annotate` or :meth:`.QuerySet.alias` on
16+
PostgreSQL.
17+
1018
Bugfixes
1119
========
1220

docs/releases/5.1.15.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ Django 5.1.15 release notes
77
Django 5.1.15 fixes one security issue with severity "high", one security issue
88
with severity "moderate", and one bug in 5.1.14.
99

10+
CVE-2025-13372: Potential SQL injection in ``FilteredRelation`` column aliases on PostgreSQL
11+
============================================================================================
12+
13+
:class:`.FilteredRelation` was subject to SQL injection in column aliases,
14+
using a suitably crafted dictionary, with dictionary expansion, as the
15+
``**kwargs`` passed to :meth:`.QuerySet.annotate` or :meth:`.QuerySet.alias` on
16+
PostgreSQL.
17+
1018
Bugfixes
1119
========
1220

tests/annotations/tests.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from decimal import Decimal
33

44
from django.core.exceptions import FieldDoesNotExist, FieldError
5+
from django.db import connection
56
from django.db.models import (
67
BooleanField,
78
Case,
@@ -1454,3 +1455,14 @@ def test_alias_filtered_relation_sql_injection(self):
14541455
)
14551456
with self.assertRaisesMessage(ValueError, msg):
14561457
Book.objects.alias(**{crafted_alias: FilteredRelation("authors")})
1458+
1459+
def test_alias_filtered_relation_sql_injection_dollar_sign(self):
1460+
qs = Book.objects.alias(
1461+
**{"crafted_alia$": FilteredRelation("authors")}
1462+
).values("name", "crafted_alia$")
1463+
if connection.vendor == "postgresql":
1464+
msg = "Dollar signs are not permitted in column aliases on PostgreSQL."
1465+
with self.assertRaisesMessage(ValueError, msg):
1466+
list(qs)
1467+
else:
1468+
self.assertEqual(qs.first()["name"], self.b1.name)

0 commit comments

Comments
 (0)