Skip to content

Commit bf70c6a

Browse files
committed
feat: Add explicit comments in runFindTriggers, triggers.js
1 parent 041b00d commit bf70c6a

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

src/rest.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ async function runFindTriggers(
3434
options = {}
3535
) {
3636
const { isGet } = options;
37+
38+
// Run beforeFind trigger - may modify query or return objects directly
3739
const result = await triggers.maybeRunQueryTrigger(
3840
triggers.Types.beforeFind,
3941
className,
@@ -48,11 +50,14 @@ async function runFindTriggers(
4850
restWhere = result.restWhere || restWhere;
4951
restOptions = result.restOptions || restOptions;
5052

53+
// Short-circuit path: beforeFind returned objects directly
54+
// Security risk: These objects may have been fetched with master privileges
5155
if (result?.objects) {
5256
const objectsFromBeforeFind = result.objects;
5357

5458
let objectsForAfterFind = objectsFromBeforeFind;
5559

60+
// Security check: Re-filter objects if not master to ensure ACL/CLP compliance
5661
if (!auth?.isMaster && !auth?.isMaintenance) {
5762
const ids = (Array.isArray(objectsFromBeforeFind) ? objectsFromBeforeFind : [objectsFromBeforeFind])
5863
.map(o => (o && (o.id || o.objectId)) || null)
@@ -61,6 +66,7 @@ async function runFindTriggers(
6166
if (ids.length > 0) {
6267
const refilterWhere = isGet ? { objectId: ids[0] } : { objectId: { $in: ids } };
6368

69+
// Re-query with proper security: no triggers to avoid infinite loops
6470
const refilterQuery = await RestQuery({
6571
method: isGet ? RestQuery.Method.get : RestQuery.Method.find,
6672
config,
@@ -79,6 +85,7 @@ async function runFindTriggers(
7985
}
8086
}
8187

88+
// Run afterFind trigger on security-filtered objects
8289
const afterFindProcessedObjects = await triggers.maybeRunAfterFindTrigger(
8390
triggers.Types.afterFind,
8491
auth,
@@ -95,6 +102,7 @@ async function runFindTriggers(
95102
};
96103
}
97104

105+
// Normal path: execute database query with modified conditions
98106
const query = await RestQuery({
99107
method: isGet ? RestQuery.Method.get : RestQuery.Method.find,
100108
config,

src/triggers.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ export function maybeRunAfterFindTrigger(
463463
}
464464

465465
const request = getRequestObject(triggerType, auth, null, null, config, context, isGet);
466+
// Convert query parameter to Parse.Query instance
466467
if (query instanceof Parse.Query) {
467468
request.query = query;
468469
} else if (typeof query === 'object' && query !== null) {
@@ -496,6 +497,8 @@ export function maybeRunAfterFindTrigger(
496497
auth,
497498
config.logLevels.triggerBeforeSuccess
498499
);
500+
501+
// Convert plain objects to Parse.Object instances for trigger
499502
request.objects = objectsInput.map(currentObject => {
500503
if (currentObject instanceof Parse.Object) {
501504
return currentObject;

0 commit comments

Comments
 (0)