File CVE-2025-13372.patch of Package python-Django.19255
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
Index: Django-2.2.28/django/db/backends/postgresql/compiler.py
===================================================================
--- /dev/null
+++ Django-2.2.28/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)
Index: Django-2.2.28/django/db/backends/postgresql/operations.py
===================================================================
--- Django-2.2.28.orig/django/db/backends/postgresql/operations.py
+++ Django-2.2.28/django/db/backends/postgresql/operations.py
@@ -6,6 +6,7 @@ from django.db.backends.base.operations
class DatabaseOperations(BaseDatabaseOperations):
+ compiler_module = "django.db.backends.postgresql.compiler"
cast_char_field_without_max_length = 'varchar'
explain_prefix = 'EXPLAIN'
explain_options = frozenset(
Index: Django-2.2.28/tests/annotations/tests.py
===================================================================
--- Django-2.2.28.orig/tests/annotations/tests.py
+++ Django-2.2.28/tests/annotations/tests.py
@@ -2,6 +2,7 @@ import datetime
from decimal import Decimal
from django.core.exceptions import FieldDoesNotExist, FieldError
+from django.db import connection
from django.db.models import (
BooleanField, CharField, Count, DateTimeField, ExpressionWrapper, F, Func,
FilteredRelation, IntegerField, NullBooleanField, OuterRef, Q, Subquery, Sum, Value,
@@ -647,3 +648,15 @@ class NonAggregateAnnotationTestCase(Tes
Book.objects.annotate(
**{crafted_alias: FilteredRelation("authors")}
)
+
+ def test_alias_filtered_relation_sql_injection_dollar_sign(self):
+ qs = Book.objects.annotate(
+ **{"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)
+