Skip to content

Commit f41a94b

Browse files
committed
Fix: wrap string values in $literal to prevent expression misinterpretation
1 parent 30cf189 commit f41a94b

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

django_mongodb_backend/expressions/builtins.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ def when(self, compiler, connection):
211211

212212
def value(self, compiler, connection, as_expr=False): # noqa: ARG001
213213
value = self.value
214-
if isinstance(value, (list, int)) and as_expr:
215-
# Wrap lists & numbers in $literal to prevent ambiguity when Value
216-
# appears in $project.
214+
if isinstance(value, (list, int, str)) and as_expr:
215+
# Wrap lists, numbers, and strings in $literal to avoid ambiguity when Value
216+
# is used in queries' aggregate or update_many's $set.
217217
return {"$literal": value}
218218
if isinstance(value, Decimal):
219219
return Decimal128(value)

tests/basic_/tests.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.db.models import Value
12
from django.test import TestCase
23

34
from django_mongodb_backend.test import MongoTestCaseMixin
@@ -11,3 +12,18 @@ def test_insert_dollar_prefix(self):
1112
obj = Author.objects.create(name="$foobar")
1213
obj.refresh_from_db()
1314
self.assertEqual(obj.name, "$foobar")
15+
16+
17+
class QueryDollarPrefixTests(MongoTestCaseMixin, TestCase):
18+
def test_query_injection(self):
19+
"""$-prefixed Value() expressions are correctly handled on update."""
20+
Author.objects.create(name="Gustavo")
21+
Author.objects.create(name="Walter")
22+
with self.assertNumQueries(1) as ctx:
23+
qs = list(Author.objects.annotate(a_value=Value("$name")))
24+
self.assertTrue(all(v.a_value == "$name" for v in qs))
25+
self.assertAggregateQuery(
26+
ctx.captured_queries[0]["sql"],
27+
"basic__author",
28+
[{"$project": {"a_value": {"$literal": "$name"}, "_id": 1, "name": 1}}],
29+
)

tests/model_fields_/test_embedded_model_array.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,18 @@ def test_nested_array_index_expr(self):
327327
},
328328
{
329329
"$concat": [
330-
{"$ifNull": ["Z", ""]},
331-
{"$ifNull": ["acarias", ""]},
330+
{
331+
"$ifNull": [
332+
{"$literal": "Z"},
333+
{"$literal": ""},
334+
]
335+
},
336+
{
337+
"$ifNull": [
338+
{"$literal": "acarias"},
339+
{"$literal": ""},
340+
]
341+
},
332342
]
333343
},
334344
]

0 commit comments

Comments
 (0)