The predicate inside arrayFilters for update does not ban query language "extensions" such as text search, geospatial search, and JavaScript execution. Although top-level predicates like $where and $text are disallowed inside arrayFilters by this check, this becomes a problem for geoNear:
> db.c.drop() true > db.c.insert({a: [1, 4, 9]}) WriteResult({ "nInserted" : 1 }) > db.c.update({}, {$set: {"a.$[i]": 9}}, {arrayFilters: [{"i": {$near: {$geometry: {type: "Point", coordinates: [0, 0]}}}}]}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.c.find() { "_id" : ObjectId("594d79c59af796e3dcf96707"), "a" : [ 9, 9, 9 ] }
The update should fail, but instead it modifies all elements in the array. This is because geoNear has a stub MatchExpression node which doesn't actually get used for matching:
A fix for this issue will likely involve using ExtensionsCallbackDisallowExtensions rather than ExtensionsCallbackReal while parsing the array filters. This would fix the geoNear problem, as well as improve the error message for $text and $where. We should also quickly audit the list of match expression operators to make sure that there is nothing else which needs to be banned inside arrayFilters.