[Django] #36912: Q.create() doesn't validate connectors as Q.__init__() does

1 view
Skip to first unread message

Django

unread,
Feb 9, 2026, 5:30:09 PM (2 days ago) Feb 9
to django-...@googlegroups.com
#36912: Q.create() doesn't validate connectors as Q.__init__() does
-------------------------------------+-------------------------------------
Reporter: Jacob | Owner: Sarah Boyce
Walls |
Type: | Status: assigned
Cleanup/optimization |
Component: Database | Version: dev
layer (models, ORM) |
Severity: Normal | Keywords: _connector security
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
In 98e642c69181c942d60a10ca0085d48c6b3068bb, we mitigated a SQL injection
vector for user-controlled arguments to `filter()` and friends
(CVE-2025-64459) by adding validation for the `_connector` argument.

We deliberately avoided adding the same validation to `Q.create()`,
because `Q.create` is an undocumented internal not to be used with user-
controlled input.

The Security Team then received more than one report extrapolating from
CVE-2025-64459, suggesting that `Q.create` was missing the same
validation.

Although we don't consider this a security vulnerability, we would be
interested to evaluate if adding validation to `Q.create` to match
`Q.__init__` would be cheap enough to implement. A concern is how many
times `Q.create` might be called in loops. Thus, one part of the solution
here might be a refactor to reduce the number of times `Q.create` is
called in loops in Django's code:

in `contrib.contenttypes`:
https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/contrib/contenttypes/fields.py#L682-L695
in the deletion `Collector`:
https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/db/models/deletion.py#L357-L358
...others?
----
Tentatively passing over to Djangonaut Space navigators to see if a good
fit for anyone (git archaeology, benchmarking, security, ORM internals)
--
Ticket URL: <https://code.djangoproject.com/ticket/36912>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Feb 9, 2026, 5:36:45 PM (2 days ago) Feb 9
to django-...@googlegroups.com
#36912: Q.create() doesn't validate connectors as Q.__init__() does
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner: Sarah
Type: | Boyce
Cleanup/optimization | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: _connector security | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Jacob Walls:

Old description:

> In 98e642c69181c942d60a10ca0085d48c6b3068bb, we mitigated a SQL injection
> vector for user-controlled arguments to `filter()` and friends
> (CVE-2025-64459) by adding validation for the `_connector` argument.
>
> We deliberately avoided adding the same validation to `Q.create()`,
> because `Q.create` is an undocumented internal not to be used with user-
> controlled input.
>
> The Security Team then received more than one report extrapolating from
> CVE-2025-64459, suggesting that `Q.create` was missing the same
> validation.
>
> Although we don't consider this a security vulnerability, we would be
> interested to evaluate if adding validation to `Q.create` to match
> `Q.__init__` would be cheap enough to implement. A concern is how many
> times `Q.create` might be called in loops. Thus, one part of the solution
> here might be a refactor to reduce the number of times `Q.create` is
> called in loops in Django's code:
>
> in `contrib.contenttypes`:
> https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/contrib/contenttypes/fields.py#L682-L695
> in the deletion `Collector`:
> https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/db/models/deletion.py#L357-L358
> ...others?
> ----
> Tentatively passing over to Djangonaut Space navigators to see if a good
> fit for anyone (git archaeology, benchmarking, security, ORM internals)

New description:

In 98e642c69181c942d60a10ca0085d48c6b3068bb, we mitigated a SQL injection
vector for user-controlled arguments to `filter()` and friends
(CVE-2025-64459) by adding validation for the `_connector` argument.

We deliberately avoided adding the same validation to `Q.create()`,
because `Q.create` is an undocumented internal not to be used with user-
controlled field names.

The Security Team then received more than one report extrapolating from
CVE-2025-64459, suggesting that `Q.create` was missing the same
validation.

Although we don't consider this a security vulnerability, we would be
interested to evaluate if adding validation to `Q.create` to match
`Q.__init__` would be cheap enough to implement. A concern is how many
times `Q.create` might be called in loops. Thus, one part of the solution
here might be a refactor to reduce the number of times `Q.create` is
called in loops in Django's code:

in `contrib.contenttypes`:
https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/contrib/contenttypes/fields.py#L682-L695
in the deletion `Collector`:
https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/db/models/deletion.py#L357-L358
...others?
----
Tentatively passing over to Djangonaut Space navigators to see if a good
fit for anyone (git archaeology, benchmarking, security, ORM internals)

--
--
Ticket URL: <https://code.djangoproject.com/ticket/36912#comment:1>

Django

unread,
Feb 9, 2026, 5:43:32 PM (2 days ago) Feb 9
to django-...@googlegroups.com
#36912: Q.create() doesn't validate connectors as Q.__init__() does
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner: Sarah
Type: | Boyce
Cleanup/optimization | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: _connector security | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Jacob Walls:

Old description:

> In 98e642c69181c942d60a10ca0085d48c6b3068bb, we mitigated a SQL injection
> vector for user-controlled arguments to `filter()` and friends
> (CVE-2025-64459) by adding validation for the `_connector` argument.
>
> We deliberately avoided adding the same validation to `Q.create()`,
> because `Q.create` is an undocumented internal not to be used with user-
> controlled field names.
>
> The Security Team then received more than one report extrapolating from
> CVE-2025-64459, suggesting that `Q.create` was missing the same
> validation.
>
> Although we don't consider this a security vulnerability, we would be
> interested to evaluate if adding validation to `Q.create` to match
> `Q.__init__` would be cheap enough to implement. A concern is how many
> times `Q.create` might be called in loops. Thus, one part of the solution
> here might be a refactor to reduce the number of times `Q.create` is
> called in loops in Django's code:
>
> in `contrib.contenttypes`:
> https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/contrib/contenttypes/fields.py#L682-L695
> in the deletion `Collector`:
> https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/db/models/deletion.py#L357-L358
> ...others?
> ----
> Tentatively passing over to Djangonaut Space navigators to see if a good
> fit for anyone (git archaeology, benchmarking, security, ORM internals)

New description:

In 98e642c69181c942d60a10ca0085d48c6b3068bb, we mitigated a SQL injection
vector for user-controlled arguments to `filter()` and friends
(CVE-2025-64459) by adding validation for the `_connector` argument.

We deliberately avoided adding the same validation to `Q.create()`,
because `Q.create` is an undocumented internal not to be used with user-
controlled field names and was created specifically for the purpose of
speed.

The Security Team then received more than one report extrapolating from
CVE-2025-64459, suggesting that `Q.create` was missing the same
validation.

Although we don't consider this a security vulnerability, we would be
interested to evaluate if adding validation to `Q.create` to match
`Q.__init__` would be cheap enough to implement. A concern is how many
times `Q.create` might be called in loops. Thus, one part of the solution
here might be a refactor to reduce the number of times `Q.create` is
called in loops in Django's code:

in `contrib.contenttypes`:
https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/contrib/contenttypes/fields.py#L682-L695
in the deletion `Collector`:
https://github.com/django/django/blob/13299a6203f4bc3e5b2552c96a51ff2b15da3c43/django/db/models/deletion.py#L357-L358
...others?
----
Tentatively passing over to Djangonaut Space navigators to see if a good
fit for anyone (git archaeology, benchmarking, security, ORM internals)

--
--
Ticket URL: <https://code.djangoproject.com/ticket/36912#comment:2>

Django

unread,
Feb 11, 2026, 4:01:39 PM (11 hours ago) Feb 11
to django-...@googlegroups.com
#36912: Q.create() doesn't validate connectors as Q.__init__() does
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner: Sarah
Type: | Boyce
Cleanup/optimization | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: _connector security | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* stage: Unreviewed => Accepted

Comment:

Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/36912#comment:3>
Reply all
Reply to author
Forward
0 new messages