From 5cd875813fdec5a3c40a0358b30a347967c85c14 Mon Sep 17 00:00:00 2001 From: Lauri Ojansivu Date: Mon, 29 Dec 2025 16:58:26 +0200 Subject: [PATCH] Security Fix 7: Checklist create IDOR: cardId not verified against boardId. Thanks to Joshua Rogers of joshua.hu, Twitter MegaManSec ! --- models/checklists.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/models/checklists.js b/models/checklists.js index 8d95b6f17..1a906ccaa 100644 --- a/models/checklists.js +++ b/models/checklists.js @@ -290,6 +290,20 @@ if (Meteor.isServer) { const paramBoardId = req.params.boardId; const paramCardId = req.params.cardId; Authentication.checkBoardAccess(req.userId, paramBoardId); + + // Verify the card belongs to the board + const card = ReactiveCache.getCard({ + _id: paramCardId, + boardId: paramBoardId, + }); + if (!card) { + JsonRoutes.sendResult(res, { + code: 404, + data: { error: 'Card not found or does not belong to the specified board' }, + }); + return; + } + const checklists = ReactiveCache.getChecklists({ cardId: paramCardId }).map(function( doc, ) { @@ -335,6 +349,20 @@ if (Meteor.isServer) { const paramChecklistId = req.params.checklistId; const paramCardId = req.params.cardId; Authentication.checkBoardAccess(req.userId, paramBoardId); + + // Verify the card belongs to the board + const card = ReactiveCache.getCard({ + _id: paramCardId, + boardId: paramBoardId, + }); + if (!card) { + JsonRoutes.sendResult(res, { + code: 404, + data: { error: 'Card not found or does not belong to the specified board' }, + }); + return; + } + const checklist = ReactiveCache.getChecklist({ _id: paramChecklistId, cardId: paramCardId, @@ -384,6 +412,20 @@ if (Meteor.isServer) { const addPermission = allowIsBoardMemberCommentOnly(req.userId, board); Authentication.checkAdminOrCondition(req.userId, addPermission); const paramCardId = req.params.cardId; + + // Verify the card belongs to the board + const card = ReactiveCache.getCard({ + _id: paramCardId, + boardId: paramBoardId, + }); + if (!card) { + JsonRoutes.sendResult(res, { + code: 404, + data: { error: 'Card not found or does not belong to the specified board' }, + }); + return; + } + const id = Checklists.insert({ title: req.body.title, cardId: paramCardId,