Releases: wekan/wekan
Release list
v10.37
v10.37 2026-07-25 WeKan ® release
This release fixes the following SECURITY ISSUES found by GitHub CodeQL code
scanning:
js/incomplete-sanitization(High), alert #428, in
tests/boardHeaderOneLine.test.cjs: the CSS rule bodies were split with
rule.split('{')and the trailing brace removed withbody.replace('}', ''),
which strips only the FIRST}. The block is now matched with one regex that
captures selector and body as separate groups, so no brace ends up in the text
and there is nothing to strip.js/incomplete-sanitization(High), alert #427, in
tests/testsAreRegistered.test.cjs: a file name was spliced into aRegExp
after escaping only dots, leaving every other metacharacter — the backslash
above all — able to change the meaning of the pattern. It now goes through an
escapeRegExp()that escapes the full set, backslash included.- Both are test helpers, so neither was reachable by an attacker, but both were
genuinely wrong string handling
(commit). - Thanks to GitHub CodeQL (alerts #427 and #428) and xet7.
and resolves the following GitHub Dependabot alerts in npm dependencies:
- brace-expansion 5.0.7 → 5.0.8 (RUNTIME dependency, transitive via
minimatch):
fixes CVE-2026-14257
(GHSA-mh99-v99m-4gvg, High, CVSS 7.5, alert #119) —expand()bounds how MANY
results it produces (max, 100000) but not how LONG they get, so chained brace
groups keep the count under the cap while every result grows one character per
group. A ~7.5 KB input ('{a,b}'.repeat(1500)) exhausts memory and kills the Node
process with a fatal, uncatchable out-of-memory error thattry/catchcannot
contain. 5.0.8 bounds the total characters oneexpand()call may accumulate
(maxLength, default 4000000) inside the output-building loops, so intermediate
arrays are bounded too and oversized input is truncated rather than fatal. Patch
release in the same major line; the only other change isengines.node, which drops
Node 18 — WeKan builds and ships on Node 24 (DockerfileNODE_VERSION=v24.18.0, CI
NODE_VERSION: '24'), so nothing is affected
(#6523, merge commit). - postcss 8.5.15 → 8.5.22 (dev dependency; enters only through
css-loader, which
the rspack build uses for.css, and is not itself part of the shipped bundle):
fixes GHSA-r28c-9q8g-f849
(High, CVSS 7.5) — postcss follows a/*# sourceMappingURL=... */comment in the CSS
it parses and builds the path withpath.join(dirname(from), annotation), which
normalises but does not sandbox.., so a crafted comment discloses arbitrary.map
files. Affected<= 8.5.17, patched in 8.5.18.nanoid 3.3.12 → 3.3.16rides along
as postcss's own dependency
(#6522, merge commit). - Both are lock-only changes whose tarball integrity hashes were verified against the
npm registry, and the brace-expansion lock edit was reproduced independently with
npm update brace-expansion --package-lock-only, which produced a byte-identical
diff.elliptic(alert #55, CVE-2025-14505) is still left pinned for the reason
recorded in v10.14: no fixed version is published upstream — the latest release is
still 6.6.1 and the advisory lists no patched version. It is a dev-only transitive
polyfill (@meteorjs/rspack→node-stdlib-browser→crypto-browserify→
browserify-sign/create-ecdh), no WeKan client module imports nodecrypto, and
the built client bundle contains noelliptic/secp256k1/crypto-browserifycode
at all, so it never reaches users. - Thanks to GitHub Dependabot and xet7.
and has the following developer-tooling fix:
Thanks to above GitHub users for their contributions and translators for their
translations.
v10.36
v10.36 2026-07-25 WeKan ® release
This release fixes the following bugs:
- The Change profile image window (Member settings > Change Avatar, and the same
window in Admin Panel > People) rendered each avatar row's "Delete" link and file
name INSIDE the row's select link. An<a>inside an<a>is invalid HTML: the
browser closes the outer anchor, so the file name and the Delete link fell out of
the row's flex layout and rendered as bold text floating at the right edge, and a
click on Delete also selected that avatar. Delete and the file name were shown only
for the avatar currently in use, so no other upload could ever be deleted, and an
emptyp.sub-nameadded a stray block in the middle of the row. Each row is now one
flex line - thumbnail, file name (truncated with the full name as a tooltip), a
check mark when it is the avatar in use, and a delete button that is a SIBLING of
the select link, so deleting never also selects and every uploaded avatar can be
deleted. The row in use is highlighted like in the other pop-over lists, the
initials row shows its "Default avatar" label under the name, and the upload hints
(max filesize, allowed filetypes, invalid filename) are grouped into one muted
paragraph above the upload button. Deleting the avatar in use left
profile.avatarUrlpointing at a file that no longer existed - a broken image
everywhere - so both windows now fall back to the initials when the deleted file is
the one in use. The Admin Panel window also passeduserData=to
userAvatarInitials, which readsthis.userId, so its initials rendered
empty.
Thanks to xet7. - On iPad Safari a full-screen "Uncaught runtime errors: ERROR Script error." panel
appeared after login, and again when the Safari Share sheet was opened on All Boards
to add WeKan to the home screen. That panel is webpack-dev-server's error overlay,
shipped by the rspack DEV server only - a production build has no dev server and no
overlay. It opens for every windowerrorevent, including ones that carry no
information: a browser sanitises an error thrown by a CROSS-ORIGIN script to the bare
message "Script error." with no error object and no stack, and iOS Safari raises those
from its own machinery and from content blockers and extensions, which is what the
Share sheet triggered. It cannot come from WeKan's own code, because the bundle is
served same-origin (noCDN_URL), so a real WeKan error always reaches the overlay
with its actual message and stack. The overlay now ignores exactly that one message
and still shows every other runtime error and all compile
errors.
Thanks to xet7. - The board bar (the second header bar) fits on one line on iPad. In landscape it
wrapped onto two rows - board title, edit, visibility, watch, star and sort on the
first, Filter / Search / view / dependencies / multi-selection / hamburger on the
second. Measured at a 1180 CSS px viewport the two rows needed about 1304px on one
line, ~124px more than the viewport, and nearly all of that is per-button empty space
rather than text: each button carries 12px side margins, 10px on each side of its icon
and a 10px gap after its label, about 54px of chrome around a ~60px icon+label. So
nothing has to be hidden at that width: halving the chrome between 801px and 1400px
frees ~295px, which fits the bar on one line with room to spare for languages with
longer labels, and icon and label sizes are untouched so the buttons stay comfortable
to tap. In tablet portrait (820px), where even the halved chrome cannot fit the labels,
they drop to icons only between 801px and 1000px - the same treatment phones already
get below 801px, with titles, tooltips and popups unchanged. Wide desktops, which never
wrapped, look exactly as before, and phones keep their 44px touch
targets.
Thanks to xet7. - A long board title now moves ALL of the board bar's buttons to its second row,
under the title. Before, the controls were split across the two rows: the title kept
the left group (edit, visibility, watch, star, sort) beside it and only the right
group (Filter, Search, view, dependencies, multi-selection, hamburger) wrapped
underneath. That is what separate flex items do - the title and the three button
groups were four children of the header row, so the row broke wherever it ran out of
width. The three groups now live inside one wrapper, so the row has just two items,
the title and the buttons, and either the buttons fit beside the title or the whole
set moves down together. A short title is unaffected, because the wrapper measures as
its own content width and only moves down when it genuinely does not fit. A title
longer than the whole bar now wraps inside the title instead of overflowing the
viewport.
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their
translations.
v10.35
v10.35 2026-07-24 WeKan ® release
This release fixes the following bugs:
and has the following developer-tooling changes:
Thanks to above GitHub users for their contributions and translators for their translations.
v10.34
v10.34 2026-07-24 WeKan ® release
This release adds the following new features:
and fixes the following bugs:
-
[Every bundled binary now runs through
cpu-execon Sandstorm and in the snap, so a CPU
missing an instruction-set feature falls back to qemu-user instead of killing the app
with SIGILL.cpu-exec(#6458) exists for exactly that — AVX masked by a hypervisor
(QEMU/KVM/Proxmox), an old CPU, ARMv8.0 on a Raspberry Pi — and with no features
declared it is a plain exec, which is why the design is to route everything through it.
Sandstorm SHIPPEDcpu-execandqemu-x86_64but its grain launcher spawned all eight
bundled binaries directly (ferretdb, mongod 3.0 twice, niscud, the legacy mongo CLI
twice, and node for the bridge and the importer), so the safety net sat in the package
unreachable — on the platform with the least control over its hardware, since a grain
runs on wha...
v10.33
v10.33 2026-07-23 WeKan ® release
This release adds the following updates:
- Added anupamme of OrbisAI Security to Hall of Shame: Fake AI.
Part 1,
Part 2.
Thanks to anypamme.
and fixes the following bugs:
Thanks to above GitHub users for their contributions and translators for their translations.
v10.32
v10.32 2026-07-23 WeKan ® release
This release fixes the following bugs:
-
[Fix #6511 and #6514 (and the v10.30–10.31 Docker / Sandstorm / production "board
maintenance spinner", missing top user/settings bar, and login-form-not-rendering
reports): the whole client broke withUncaught Error: ES Modules may not assign module.exports or exports.*followed byError: No such template: swimlane/
notifications/boardButtons.imports/collectionHelpers.js— a side-effect shim
imported FIRST inclient/main.js— ended withmodule.exports = {}while referencing
the Meteor pseudo-globalPackagebare; the client rspack build's ProvidePlugin rewrites
Packageinto an injected ESMimport, marking the file an ES module, and an ES module
that assignsmodule.exportsthrows at evaluation time. That threw before any template
registered, so Blaze reported "No such template" for the board and header templates, the
board stayed on the spinner, the top bar was missing and the board went blank grey after
login. It reproduced on the official root-domainboards.wekan.teamand on plain Docker
with no reverse proxy (ROOT_URL=http://neptun:4001), so it was a global build bug, not a
reverse-proxy / sub-path issue.collectionHelpers(the first such file) was fixed to
useexport {},
and then a transitive walk fromclient/main.jsfound and converted EVERY remaining
client-reachable CommonJS helper (~55 files undermodels/lib,client/lib,
imports/lib,imports/) frommodule.exports = { … }toexport { … }, so nothing in
the client bundle assignsmodule.exportsany more — done in
two
parts.
Server-only helpers (theserver/libfiles Meteor never ships to the client, and the
fs-using file-storage helpers) stay CommonJS. Their plain-Node.cjsunit tests now use
await import(…js); the fulltests/*.test.cjssuite has no new failures. This is NOT an
rspack version regression — the lockfile has pinned@rspack/core ~1.7.xsince v8.40,
unchanged between the working v10.17 and the broken v10.27.
Thanks to mueschel, jullbo, akshat-goel, AmigaAbattoir and xet7.
and updates the following dependencies:
and has the following developer-tooling fix:
and improves the translation workflow:
Thanks to above GitHub users for their contributions and translators for their translations.
v10.31
v10.31 2026-07-23 WeKan ® release
This release fixes the following bugs:
Thanks to above GitHub users for their contributions and translators for their translations.
v10.30
v10.30 2026-07-23 WeKan ® release
This release updates the following dependencies:
- The bundled FerretDB v1 fork now creates the OpLog
tsindex on the PostgreSQL, MySQL
and SAP HANA backends too (previously only SQLite), so an idle Meteor OpLog tail resumes
with an index range scan instead of re-scanning the whole capped collection on every
poll. Best-effort per backend, with a descriptive log if a live engine rejects the index
syntax (see the FerretDB fork changelog). Ships with the bundled FerretDB update. Thanks
to xet7.
This release fixes the following bugs:
Thanks to above GitHub users for their contributions and translators for their translations.
v10.29
v10.29 2026-07-23 WeKan ® release
This release adds the following new features:
This release fixes the following bugs:
Thanks to above GitHub users for their contributions and translators for their translations.
v10.28
v10.28 2026-07-23 WeKan ® release
This release fixes the following bugs:
-
Opening a card no longer takes ~40 seconds on FerretDB v1 (SQLite). A card's attachments are
looked up with the dotted key{'meta.cardId': ...}, which the bundled FerretDB dropped from the
WHERE (it skipped any dotted-path key), so it full-scanned the wholeattachmentscollection with
a per-row decode on every poll while a card was open — slow card content and high idle CPU. The
FerretDB v1 fork now pushes down a dotted-path equality/$inas the nested->expression that
matches the existingmeta.cardIdindex (see the FerretDB fork changelog). Ships with the bundled
FerretDB update. Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.