summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2026-01-21 18:00:13 -0500
committerJacob Walls <jacobtylerwalls@gmail.com>2026-02-03 08:05:34 -0500
commit259dff061a9ea85f061ff71c0adb0e07ead693d3 (patch)
treeb3a806cb511ed5479847ca016343c053a274bc37
parent15e70cb83e6f7a9a2a2f651f30b28b5cb20febeb (diff)
[6.0.x] Refs CVE-2026-1312 -- Raised ValueError when FilteredRelation aliases contain periods.
This prevents failures at the database layer, given that aliases in the ON clause are not quoted. Systematically quoting aliases even in FilteredRelation is tracked in https://code.djangoproject.com/ticket/36795. Backport of 005d60d97c4dfb117503bdb6f2facfcaf9315d84 from main.
-rw-r--r--django/db/models/sql/query.py5
-rw-r--r--tests/filtered_relation/tests.py13
-rw-r--r--tests/ordering/tests.py11
3 files changed, 26 insertions, 3 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 9eaaec1c8a..12d1a6a937 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1726,6 +1726,11 @@ class Query(BaseExpression):
return target_clause, needed_inner
def add_filtered_relation(self, filtered_relation, alias):
+ if "." in alias:
+ raise ValueError(
+ "FilteredRelation doesn't support aliases with periods "
+ "(got %r)." % alias
+ )
self.check_alias(alias)
filtered_relation.alias = alias
relation_lookup_parts, relation_field_parts, _ = self.solve_lookup_type(
diff --git a/tests/filtered_relation/tests.py b/tests/filtered_relation/tests.py
index cdcd5c19af..e263307193 100644
--- a/tests/filtered_relation/tests.py
+++ b/tests/filtered_relation/tests.py
@@ -216,6 +216,19 @@ class FilteredRelationTests(TestCase):
str(queryset.query),
)
+ def test_period_forbidden(self):
+ msg = (
+ "FilteredRelation doesn't support aliases with periods (got 'book.alice')."
+ )
+ with self.assertRaisesMessage(ValueError, msg):
+ Author.objects.annotate(
+ **{
+ "book.alice": FilteredRelation(
+ "book", condition=Q(book__title__iexact="poem by alice")
+ )
+ }
+ )
+
def test_multiple(self):
qs = (
Author.objects.annotate(
diff --git a/tests/ordering/tests.py b/tests/ordering/tests.py
index afe2e3c22c..008f0239b3 100644
--- a/tests/ordering/tests.py
+++ b/tests/ordering/tests.py
@@ -18,7 +18,6 @@ from django.db.models import (
When,
)
from django.db.models.functions import Length, Upper
-from django.db.utils import DatabaseError
from django.test import TestCase
from .models import (
@@ -411,13 +410,19 @@ class OrderingTests(TestCase):
self.assertNotEqual(qs[0].headline, "Backdated")
relation = FilteredRelation("author")
- qs2 = Article.objects.annotate(**{crafted: relation}).order_by(crafted)
- with self.assertRaises(DatabaseError):
+ msg = (
+ "FilteredRelation doesn't support aliases with periods "
+ "(got 'ordering_article.pub_date')."
+ )
+ with self.assertRaisesMessage(ValueError, msg):
+ qs2 = Article.objects.annotate(**{crafted: relation}).order_by(crafted)
# Before, unlike F(), which causes ordering expressions to be
# replaced by ordinals like n in ORDER BY n, these were ordered by
# pub_date instead of author.
# The Article model orders by -pk, so sorting on author will place
# first any article by author2 instead of the backdated one.
+ # This assertion is reachable if FilteredRelation.__init__() starts
+ # supporting periods in aliases in the future.
self.assertNotEqual(qs2[0].headline, "Backdated")
def test_order_by_pk(self):