Wekan logo

Wekan

Open source kanban board application built with Meteor

Alternative to: trello


About Versions (218)

v10.23

2026-07-22

v10.23 2026-07-22 WeKan ® release

This release fixes the following CRITICAL VULNERABILITIES:

  • ExportBleed: stored XSS in HTML board exports through a card-title second parse (CWE-79 Cross-site Scripting; GitHub Security Advisory GHSA-8r5p-4q9j-f5jx, severity High; client/lib/exportHTML.js). A board member could store entity-encoded markup in a card title (e.g. <img src=x onerror=...>). It stays inert on the live board — Blaze escapes it and the +viewer sanitizer neutralizes handlers, keeping the entity payload as text — but the exported index.html embedded a card-click handler that read the card title/body via .textContent (which DECODES HTML entities) and then concatenated those values into content.innerHTML. That SECOND parse revived the tag and ran it when a recipient clicked the card in the export, disclosing all data in that document (including cards added AFTER the attacker’s board membership was removed).

    • Fixed by building the modal with DOM nodes and assigning the card title/body through textContent, never innerHTML, so they are inserted as inert text (commit).
    • Thanks to koyokr (report) and xet7 (fix).
  • SpliceBleed follow-up: incomplete multi-character sanitization re-flagged in the filename markup strip (GitHub CodeQL code scanning alert #426, rule js/incomplete-multi-character-sanitization, CWE-116 Improper Encoding or Escaping of Output; imports/lib/fileNameDisplay.js). The SpliceBleed fix (#425) looped a CHAIN of six replaces to a fixpoint — runtime-safe, but CodeQL (a local check) could not attribute the fixpoint to the individual <[^>]*>? tag replace, so it kept flagging it (“this string may still contain <script”).

    • Fixed by restructuring to the proven-complete pattern used by client/lib/importDependencies.js stripHtml() (which cleared the sibling alert #421): remove template/PI/CDATA tokens (looped), then strip HTML/XML tags with a SINGLE replace(/<[^>]*>/g, '') looped to a fixed point, then drop any stray angle bracket so even an unclosed tag (a trailing <script) cannot survive. Behaviour is unchanged, and Blaze {{ }} still HTML-escapes every rendered filename, so this stays defence-in-depth (commit).
    • Thanks to GitHub CodeQL (code scanning alert #426) and xet7 (fix).

Thanks to above GitHub users for their contributions and translators for their translations.