Hall of Fame image from https://openclipart.org/detail/120343/trophy
Back to Hall of Fame Contents Back to Wekan Website

Contents / BoardBleed

CVE Vulnerability name Date Responsible Security Disclosure by Vulnerabilities
GHSA-gm7v-pc38-53jr CVE requested

BoardBleed

2026-06-11 0xzap (coordinated disclosure) and Claude

Did send detailed report with PoC!
  • 1. BoardBleed — cross-board write via collection allow rule
  • CVSS: 7.x High (AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:L)
  • Affected Wekan v9.35 and earlier
  • Fixed at Upcoming WeKan release


Details

1. BoardBleed — any authenticated user can move Cards/Lists/Swimlanes into a private board they are not a member of (CWE-284, CWE-639)

WeKan boards are membership-scoped: a private board is only readable/writable by its active members. The DDP collection write policies for Cards, Lists and Swimlanes authorize an update by checking the current (pre-update) boardId of the document and asking whether the caller has write access to that board. They never validate the new boardId an attacker supplies.

Because every logged-in user can create their own board (where they are admin and therefore have write access), an attacker can take a document they own and, in a single update, set its boardId (plus swimlaneId/listId) to a victim's private board. The allow rule sees the attacker's own source board, approves the write, and the document is relocated into a board the attacker is not a member of and cannot even read. This lets an unprivileged user inject arbitrary cards/lists/swimlanes (attacker-controlled titles, descriptions, assignees, etc.) into any private board by id, defeating board-level access control.

The Cards write policy authorized only against doc.boardId, which Meteor populates from the stored document (the fetch: ['boardId'] array), i.e. the source board:

// server/permissions/cards.js
Cards.allow({
  async update(userId, doc, fields) {
    return await canUpdateCard(userId, doc, fields);   // <-- doc.boardId = SOURCE board
  },
  fetch: ['boardId'],
});
    

There was no deny rule preventing a change of boardId. The update modifier { $set: { boardId: <victimBoard> } } passed the allow check because at evaluation time doc.boardId was still the attacker's own board, where allowIsBoardMemberWithWriteAccess returns true. The identical pattern existed for Lists (server/permissions/lists.js) and Swimlanes (server/permissions/swimlanes.js).

The standard auto-generated Meteor collection methods /cards/update, /lists/update and /swimlanes/update are callable by any authenticated DDP client directly over the Meteor websocket and were gated solely by these allow rules.

Impact: an unprivileged authenticated user could inject attacker-controlled cards, lists and swimlanes into any private board by id — for example planting a misleading card titled "invoice approvals are now routed to <attacker>" into a victim's restricted board. Confirmed live against wekanteam/wekan:latest (v9.35.0): the planted card was visible through the board owner's own authenticated REST view, so the injected document was genuinely part of the victim's private board.

2. REST API was not affected

The REST API for the same operation (PUT /api/boards/:boardId/lists/:listId/cards/:cardId with newBoardId) correctly calls Authentication.checkBoardWriteAccess(req.userId, newBoardId) on the destination board (server/models/cards.js). Only the DDP allow/deny layer, reachable directly over the Meteor websocket by any authenticated client, was vulnerable.

Fix

A shared denyCrossBoardMove(userId, modifier) helper was added in server/lib/utils.js, and a deny update rule was added to each of Cards, Lists and Swimlanes (server/permissions/cards.js, lists.js, swimlanes.js). The deny rule inspects the update modifier: when it $sets a boardId, the move is rejected unless the caller has write access (active, write-capable member) on the destination board. A cross-board move is therefore now only permitted into a board where the user is genuinely a write-capable member, while same-board edits and legitimate moves between boards the user belongs to keep working.



Timeline Details
2026-06-11 Report received from 0xzap (coordinated disclosure, GHSA-gm7v-pc38-53jr, CVE requested).
Upcoming release Fixed at Upcoming WeKan release, by denying any DDP update that moves a Card/List/Swimlane to a destination board the caller has no write access to.


Back to Hall of Fame Contents Back to Wekan Website