Batch 6 (9): dolibarr, jitsi-videobridge, zed, tryton, suricata, strawberry, zulip, zesarux, zephyr Batch 7 (15): xonotic (4), xash3d (3), xenia, xtuple, zabbix (2), zathura, zebra, yabause, zephyr-0001 Batch 8 (15): woodpecker (2), wine (4), widelands (3), wesnoth (3), wekan (3) Mix of CWE-407 and CWE-312.
3.5 KiB
WeKan — CWE-407 Disclosure Brief (wekan-0003)
2026-04-13 · Patch available — awaiting upstream merge
Finding
Three O(n²) defects in WeKan's board import system. WekanCreator in models/wekanCreator.js uses Array.some() and Array.find() for member deduplication during board import, producing O(M²) where M = members being imported. Fires on every board import operation across three separate code paths: board members, card members, and card assignees.
The Defects
wekan-0003 site 1 (PATCHED — MEDIUM): models/wekanCreator.js:323
// Board member import — O(M²) dedup:
boardToImport.members.forEach(wekanMember => {
if (wekanMember.wekanId &&
!boardToCreate.members.some(
member => member.wekanId === wekanMember.wekanId)) // O(M) per member
boardToCreate.members.push({ ...wekanMember, userId: wekanMember.wekanId });
});
wekan-0003 site 2 (PATCHED — MEDIUM): models/wekanCreator.js:410
// Card member import — O(M²) dedup:
card.members.forEach(sourceMemberId => {
const wekanId = this.members[sourceMemberId];
if (!wekanMembers.find(wId => wId === wekanId)) { // O(M) per member
wekanMembers.push(wekanId);
}
});
wekan-0003 site 3 (PATCHED — MEDIUM): models/wekanCreator.js:429
// Card assignee import — O(M²) dedup:
card.assignees.forEach(sourceMemberId => {
const wekanId = this.members[sourceMemberId];
if (!wekanAssignees.find(wId => wId === wekanId)) { // O(M) per assignee
wekanAssignees.push(wekanId);
}
});
All three sites use the same pattern: linear scan for dedup inside a forEach loop. Multiple Wekan members can map to the same user, so dedup fires frequently during cross-instance imports.
Complexity Proof
At M=200 members per board:
- Defective: 3 sites × (1 + 2 + ... + 200) = 3 × ~20,000 = ~60,000 comparisons
- Fixed: 3 × 200 Set operations = 600
- ~100× op reduction per board import.
Impact
WeKan board imports fire when migrating boards between instances, restoring backups, or importing from Trello exports. Enterprise migrations with hundreds of board members hit all three quadratic paths. Large Trello-to-WeKan migrations process thousands of cards, each with member and assignee dedup.
The Fix
Use Set for O(1) dedup at all three sites:
// Before
!boardToCreate.members.some(member => member.wekanId === wekanMember.wekanId)
// After
// CWE-407 fix: Set for O(1) dedup instead of O(M) Array.some/find.
const seenWekanIds = new Set(
boardToCreate.members.map(m => m.wekanId).filter(Boolean));
if (wekanMember.wekanId && !seenWekanIds.has(wekanMember.wekanId)) {
seenWekanIds.add(wekanMember.wekanId);
boardToCreate.members.push({ ... });
}
Patch
Fix available: defects/wekan-0003/patch/wekan-0003.patch
Single-file patch in models/wekanCreator.js. Replaces Array.some() and Array.find() with Set-based dedup at all three sites (board members, card members, card assignees). ~100× speedup at M=200.
What We Ask
A patch is ready for review.
- Confirm receipt and assign a GitHub issue reference (wekan/wekan).
- Assess severity — fires on every board import across three code paths.
- Coordinate a disclosure date — we target 90 days from first contact.
- We will credit the WeKan team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.