#36945 assigned Bug

.values() and .order_by() miss FilteredRelation when resolving aliases shadowing relationship traversals

Reported by: Jacob Walls Owned by: Sarah Boyce
Component: Database layer (models, ORM) Version: 6.0
Severity: Normal Keywords: FilteredRelation, alias
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Here is a fiddle on DryORM demonstrating that when .values()/.values_list() resolve aliases, they appropriately give priority to most aliases supplied by .annotate()/.alias() before trying to parse __ as relationship traversals, but fail to account for annotations consisting of FilteredRelation, which are stored in a different internal data structure and therefore missed.

This leads to resolving an alias that happens to contain __ as a relationship traversal instead of the alias that was requested.

Here is the reproducer:

from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType


class Person(models.Model):
    name = models.CharField(max_length=100)
    creator = models.ForeignKey(User, models.CASCADE, null=True)
    ct = models.ForeignKey(ContentType, models.CASCADE)


def run():
    admin = User.objects.create(username='admin')
    person_ct = ContentType.objects.get_for_model(Person)
    Person.objects.create(creator=admin, name="Prince", ct=person_ct)
    alias = "ct__model"
    # This does not resolve to ContentType.model. Returns Person.creator_id
    qs = Person.objects.annotate(**{alias: models.F("creator")}).values(alias)
    print(qs)
    # This does resolve to ContentType.model. Returns Person.ct.model
    qs = Person.objects.annotate(
        **{alias: models.FilteredRelation("creator", condition=models.Q(creator__isnull=False))}
    ).values(alias)
    print(qs)

Output:

<QuerySet [{'ct__model': 1}]>
<QuerySet [{'ct__model': 'person'}]>

In this example, since alias is a variable, and could be user-controlled in the case of user-configurable reports, it is unexpected that for some values of alias, the column it maps to might vary.


.order_by() is affected in the same way.


While this is not regarded as a security vulnerability, we thank sw0rdl1ght for bringing the .order_by() case to the attention of the security team.

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top