Skip to content

Commit 22f28d4

Browse files
committed
🔒 fixed issue Security: Multiple IDOR in project management methods - missing ownership checks (CWE-639)
(Fixes #246) ⬆️ updated package dependencies to latest compatible versions
1 parent 29e6b88 commit 22f28d4

3 files changed

Lines changed: 939 additions & 881 deletions

File tree

imports/api/projects/server/methods.js

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,13 @@ const updatePriority = new ValidatedMethod({
496496
},
497497
mixins: [authenticationMixin, transactionLogMixin],
498498
async run({ projectId, priority }) {
499-
await Projects.updateAsync({ _id: projectId }, { $set: { priority } })
499+
await Projects.updateAsync(
500+
{
501+
_id: projectId,
502+
$or: [{ userId: this.userId }, { admins: { $in: [this.userId] } }],
503+
},
504+
{ $set: { priority } },
505+
)
500506
return 'notifications.project_priority_success'
501507
},
502508
})
@@ -519,7 +525,17 @@ const setDefaultTaskForProject = new ValidatedMethod({
519525
},
520526
mixins: [authenticationMixin, transactionLogMixin],
521527
async run({ projectId, taskId }) {
528+
const project = await Projects.findOneAsync({
529+
_id: projectId,
530+
$or: [{ userId: this.userId }, { admins: { $in: [this.userId] } }],
531+
})
532+
if (!project) {
533+
throw new Meteor.Error('notifications.project_not_found')
534+
}
522535
const task = await Tasks.findOneAsync({ _id: taskId })
536+
if (!task || task.projectId !== projectId) {
537+
throw new Meteor.Error('notifications.task_not_found')
538+
}
523539
if (task.isDefaultTask) {
524540
await Projects.updateAsync({ _id: projectId }, { $unset: { defaultTask: 1 } })
525541
await Tasks.updateAsync({ _id: taskId }, { $set: { isDefaultTask: false } })
@@ -553,19 +569,22 @@ const setRateForUser = new ValidatedMethod({
553569
},
554570
mixins: [authenticationMixin, transactionLogMixin],
555571
async run({ projectId, userId, rate }) {
556-
const project = await Projects.findOneAsync({ _id: projectId })
557-
if (project) {
558-
const rates = project.rates || {}
559-
const rateId = JSON.parse(`{ "rates.${userId}": 1}`)
560-
if (parseFloat(rate) > 0) {
561-
rates[userId] = rate
562-
await Projects.updateAsync({ _id: projectId }, { $set: { rates } })
563-
} else {
564-
await Projects.updateAsync({ _id: projectId }, { $unset: rateId })
565-
}
566-
return 'notifications.rate_success'
572+
const project = await Projects.findOneAsync({
573+
_id: projectId,
574+
$or: [{ userId: this.userId }, { admins: { $in: [this.userId] } }],
575+
})
576+
if (!project) {
577+
throw new Meteor.Error('notifications.project_not_found')
578+
}
579+
const rates = project.rates || {}
580+
const rateId = JSON.parse(`{ "rates.${userId}": 1}`)
581+
if (parseFloat(rate) > 0) {
582+
rates[userId] = rate
583+
await Projects.updateAsync({ _id: projectId }, { $set: { rates } })
584+
} else {
585+
await Projects.updateAsync({ _id: projectId }, { $unset: rateId })
567586
}
568-
throw new Meteor.Error('notifications.project_not_found')
587+
return 'notifications.rate_success'
569588
},
570589
})
571590

0 commit comments

Comments
 (0)