New Issue Checklist
Filed publicly rather than through the security policy: this is an unhandled exception on malformed input, not a disclosure or an authentication problem. The stack trace stays in the server log, the client gets a generic 500, and the process survives, so it is a per-request failure rather than a crash.
Issue Description
reduceInRelation reads .objectId off each constraint operand without checking that the operand is an object. A null anywhere in a relation query constraint therefore raises an uncaught TypeError and the request fails with a generic 500.
Four call sites dereference unguarded (src/Controllers/DatabaseController.js, at the 9.10.1-alpha.6 tree):
if (constraintKey === 'objectId') {
relatedIds = [query[key].objectId]; // :1096
} else if (constraintKey == '$in') {
relatedIds = query[key]['$in'].map(r => r.objectId); // :1098
} else if (constraintKey == '$nin') {
isNegation = true;
relatedIds = query[key]['$nin'].map(r => r.objectId); // :1101
} else if (constraintKey == '$ne') {
isNegation = true;
relatedIds = [query[key]['$ne'].objectId]; // :1104
}
A non-object operand that is not null, for example {"$in": [7]}, is harmless: (7).objectId is undefined, which contributes no id. Only null throws, because it cannot be boxed.
This is reachable with the application id alone. No master key, session token or client key is required.
Related: #4742 reported the same shape in the same function ($in given a non-array, so .map is not a function) and was closed in 2018. The operands here are still unvalidated.
Steps to reproduce
- Create a class
Owner with a Relation field named friends, and save one object so the field is in the schema.
- Send a query whose relation constraint contains a
null:
GET /parse/classes/Owner?where={"friends":{"$in":[null]}}
X-Parse-Application-Id: <appId>
Each of these reproduces it:
| Constraint |
Result |
{"friends":{"$in":[null]}} |
500 |
{"friends":{"$nin":[null]}} |
500 |
{"friends":{"$ne":null,"$in":[]}} |
500 |
{"friends":{"$ne":null,"$nin":[]}} |
500 |
{"friends":{"$ne":null}} |
200, empty results |
The last row does not throw because a bare falsy $ne fails the gate at :1084-1090, which requires one of $in, $ne, $nin to be truthy, so the extraction loop never runs. Adding any truthy sibling operator satisfies the gate and the falsy $ne is then dereferenced. An empty array is enough, since [] is truthy.
Actual Outcome
500 {"code":1,"message":"Internal server error."}
Expected Outcome
Either Parse.Error.INVALID_JSON, or the null treated the way every other operand without an objectId is already treated: it yields undefined and contributes no related id, so the constraint resolves to no owners. The second matches the existing behavior for {"$in":[7]} and for {"$in":[{"foo":1}]}, which both return an empty result rather than an error.
Environment
Server
- Parse Server version:
9.10.1-alpha.6 (ca75b1fed69921f7843dc20b921d9b02dc352626)
- Operating system:
macOS 26.5.2
- Local or remote host:
local
Database
- System (MongoDB or Postgres):
MongoDB
- Database version:
7.0.25
- Local or remote host:
local
Client
- SDK (iOS, Android, JavaScript, PHP, Unity, etc):
REST
- SDK version:
n/a
The Postgres adapter was not tested.
Logs
TypeError: Cannot read properties of null (reading 'objectId')
at .../lib/Controllers/DatabaseController.js:946:45
at Array.map (<anonymous>)
at .../lib/Controllers/DatabaseController.js:934:43
at Array.map (<anonymous>)
at DatabaseController.reduceInRelation (.../lib/Controllers/DatabaseController.js:923:42)
at .../lib/Controllers/DatabaseController.js:1215:238
at async _UnsafeRestQuery.runFind (.../lib/RestQuery.js:785:19)
New Issue Checklist
Filed publicly rather than through the security policy: this is an unhandled exception on malformed input, not a disclosure or an authentication problem. The stack trace stays in the server log, the client gets a generic 500, and the process survives, so it is a per-request failure rather than a crash.
Issue Description
reduceInRelationreads.objectIdoff each constraint operand without checking that the operand is an object. Anullanywhere in a relation query constraint therefore raises an uncaughtTypeErrorand the request fails with a generic 500.Four call sites dereference unguarded (
src/Controllers/DatabaseController.js, at the 9.10.1-alpha.6 tree):A non-object operand that is not
null, for example{"$in": [7]}, is harmless:(7).objectIdisundefined, which contributes no id. Onlynullthrows, because it cannot be boxed.This is reachable with the application id alone. No master key, session token or client key is required.
Related: #4742 reported the same shape in the same function (
$ingiven a non-array, so.mapis not a function) and was closed in 2018. The operands here are still unvalidated.Steps to reproduce
Ownerwith aRelationfield namedfriends, and save one object so the field is in the schema.null:Each of these reproduces it:
{"friends":{"$in":[null]}}{"friends":{"$nin":[null]}}{"friends":{"$ne":null,"$in":[]}}{"friends":{"$ne":null,"$nin":[]}}{"friends":{"$ne":null}}The last row does not throw because a bare falsy
$nefails the gate at:1084-1090, which requires one of$in,$ne,$ninto be truthy, so the extraction loop never runs. Adding any truthy sibling operator satisfies the gate and the falsy$neis then dereferenced. An empty array is enough, since[]is truthy.Actual Outcome
Expected Outcome
Either
Parse.Error.INVALID_JSON, or thenulltreated the way every other operand without anobjectIdis already treated: it yieldsundefinedand contributes no related id, so the constraint resolves to no owners. The second matches the existing behavior for{"$in":[7]}and for{"$in":[{"foo":1}]}, which both return an empty result rather than an error.Environment
Server
9.10.1-alpha.6(ca75b1fed69921f7843dc20b921d9b02dc352626)macOS 26.5.2localDatabase
MongoDB7.0.25localClient
RESTn/aThe Postgres adapter was not tested.
Logs