mirror of
https://github.com/parse-community/parse-server
synced 2026-08-09 13:03:18 +00:00
fix: LiveQuery protected-field guard bypass via array-like logical operator value ([GHSA-mmg8-87c5-jrc2](https://github.com/parse-community/parse-server/security/advisories/GHSA-mmg8-87c5-jrc2)) (#10350)
This commit is contained in:
+4182
-4062
File diff suppressed because it is too large
Load Diff
@@ -555,6 +555,16 @@ class ParseLiveQueryServer {
|
||||
if (typeof where !== 'object' || where === null) {
|
||||
return;
|
||||
}
|
||||
for (const op of ['$or', '$and', '$nor']) {
|
||||
if (where[op] !== undefined && !Array.isArray(where[op])) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, `${op} must be an array`);
|
||||
}
|
||||
if (Array.isArray(where[op])) {
|
||||
where[op].forEach((subQuery: any) => {
|
||||
this._validateQueryConstraints(subQuery);
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const key of Object.keys(where)) {
|
||||
const constraint = where[key];
|
||||
if (typeof constraint === 'object' && constraint !== null) {
|
||||
@@ -582,18 +592,6 @@ class ParseLiveQueryServer {
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const op of ['$or', '$and', '$nor']) {
|
||||
if (Array.isArray(constraint[op])) {
|
||||
constraint[op].forEach((subQuery: any) => {
|
||||
this._validateQueryConstraints(subQuery);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (Array.isArray(where[key])) {
|
||||
where[key].forEach((subQuery: any) => {
|
||||
this._validateQueryConstraints(subQuery);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1048,6 +1046,9 @@ class ParseLiveQueryServer {
|
||||
return;
|
||||
}
|
||||
for (const op of ['$or', '$and', '$nor']) {
|
||||
if (where[op] !== undefined && !Array.isArray(where[op])) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, `${op} must be an array`);
|
||||
}
|
||||
if (Array.isArray(where[op])) {
|
||||
for (const subQuery of where[op]) {
|
||||
checkDepth(subQuery, depth + 1);
|
||||
@@ -1111,6 +1112,9 @@ class ParseLiveQueryServer {
|
||||
}
|
||||
}
|
||||
for (const op of ['$or', '$and', '$nor']) {
|
||||
if (where[op] !== undefined && !Array.isArray(where[op])) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, `${op} must be an array`);
|
||||
}
|
||||
if (Array.isArray(where[op])) {
|
||||
where[op].forEach((subQuery: any) => checkWhere(subQuery));
|
||||
}
|
||||
|
||||
@@ -213,6 +213,9 @@ function matchesKeyConstraints(object, key, constraints) {
|
||||
}
|
||||
var i;
|
||||
if (key === '$or') {
|
||||
if (!Array.isArray(constraints)) {
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < constraints.length; i++) {
|
||||
if (matchesQuery(object, constraints[i])) {
|
||||
return true;
|
||||
@@ -221,6 +224,9 @@ function matchesKeyConstraints(object, key, constraints) {
|
||||
return false;
|
||||
}
|
||||
if (key === '$and') {
|
||||
if (!Array.isArray(constraints)) {
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < constraints.length; i++) {
|
||||
if (!matchesQuery(object, constraints[i])) {
|
||||
return false;
|
||||
@@ -229,6 +235,9 @@ function matchesKeyConstraints(object, key, constraints) {
|
||||
return true;
|
||||
}
|
||||
if (key === '$nor') {
|
||||
if (!Array.isArray(constraints)) {
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < constraints.length; i++) {
|
||||
if (matchesQuery(object, constraints[i])) {
|
||||
return false;
|
||||
|
||||
@@ -924,6 +924,13 @@ _UnsafeRestQuery.prototype.denyProtectedFields = async function () {
|
||||
}
|
||||
}
|
||||
for (const op of ['$or', '$and', '$nor']) {
|
||||
if (where[op] !== undefined && !Array.isArray(where[op])) {
|
||||
throw createSanitizedError(
|
||||
Parse.Error.INVALID_QUERY,
|
||||
`${op} must be an array`,
|
||||
this.config
|
||||
);
|
||||
}
|
||||
if (Array.isArray(where[op])) {
|
||||
where[op].forEach(subQuery => checkWhere(subQuery));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user