File CVE-2025-13372.patch of Package python-Django.41924

From f997037b235f6b5c9e7c4a501491ec45f3400f3d Mon Sep 17 00:00:00 2001
From: Jacob Walls <jacobtylerwalls@gmail.com>
Date: Mon, 17 Nov 2025 17:09:54 -0500
Subject: [PATCH] [4.2.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 5b90ca1e7591fa36fccf2d6dad67cf1477e6293e from main.
---
 django/db/backends/postgresql/compiler.py   | 24 +++++++++++++++++++++
 django/db/backends/postgresql/operations.py |  1 +
 docs/releases/4.2.27.txt                    |  8 +++++++
 tests/annotations/tests.py                  | 12 +++++++++++
 4 files changed, 45 insertions(+)
 create mode 100644 django/db/backends/postgresql/compiler.py

diff --git a/django/db/backends/postgresql/compiler.py b/django/db/backends/postgresql/compiler.py
new file mode 100644
index 000000000000..d4140c7f98a6
--- /dev/null
+++ b/django/db/backends/postgresql/compiler.py
@@ -0,0 +1,24 @@
+from django.db.models.sql.compiler import (  # isort:skip
+    SQLAggregateCompiler,
+    SQLCompiler as BaseSQLCompiler,
+    SQLDeleteCompiler,
+    SQLInsertCompiler,
+    SQLUpdateCompiler,
+)
+
+__all__ = [
+    "SQLAggregateCompiler",
+    "SQLCompiler",
+    "SQLDeleteCompiler",
+    "SQLInsertCompiler",
+    "SQLUpdateCompiler",
+]
+
+
+class SQLCompiler(BaseSQLCompiler):
+    def quote_name_unless_alias(self, name):
+        if "$" in name:
+            raise ValueError(
+                "Dollar signs are not permitted in column aliases on PostgreSQL."
+            )
+        return super().quote_name_unless_alias(name)
diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py
index c4d90b56ab0e..24ad90e5fc3c 100644
--- a/django/db/backends/postgresql/operations.py
+++ b/django/db/backends/postgresql/operations.py
@@ -23,6 +23,7 @@ def get_json_dumps(encoder):
 
 
 class DatabaseOperations(BaseDatabaseOperations):
+    compiler_module = "django.db.backends.postgresql.compiler"
     cast_char_field_without_max_length = "varchar"
     explain_prefix = "EXPLAIN"
     explain_options = frozenset(
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index 4879f19a7848..d876e3a6f5c2 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -2,6 +2,7 @@
 from decimal import Decimal
 
 from django.core.exceptions import FieldDoesNotExist, FieldError
+from django.db import connection
 from django.db.models import (
     BooleanField,
     Case,
@@ -1443,3 +1444,14 @@ def test_alias_filtered_relation_sql_injection(self):
         )
         with self.assertRaisesMessage(ValueError, msg):
             Book.objects.alias(**{crafted_alias: FilteredRelation("authors")})
+
+    def test_alias_filtered_relation_sql_injection_dollar_sign(self):
+        qs = Book.objects.alias(
+            **{"crafted_alia$": FilteredRelation("authors")}
+        ).values("name", "crafted_alia$")
+        if connection.vendor == "postgresql":
+            msg = "Dollar signs are not permitted in column aliases on PostgreSQL."
+            with self.assertRaisesMessage(ValueError, msg):
+                list(qs)
+        else:
+            self.assertEqual(qs.first()["name"], self.b1.name)
openSUSE Build Service is sponsored by