Wekan
Open source kanban board application built with Meteor
Alternative to: trello
v10.83
2026-08-11Binaries in these bundles
Each bundle carries a Node.js, a FerretDB and the MongoDB Database Tools. Which source has a given CPU varies from release to release - nodejs.org builds some architectures, unofficial-builds others, and the wekan/node-patches build the ones neither of them does - and not every source publishes a checksum. This is what went into this release, and which downloads were checked against a published SHA256.
| Bundle | Binary | From | Version | Checked | SHA256 |
|---|---|---|---|---|---|
| amd64 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 7c74941ff043f26a… |
| amd64 | Node.js | nodejs.org | v24.19.0 | verified | 14b342e71204f811… |
| arm64 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 092132531555a39e… |
| arm64 | Node.js | nodejs.org | v24.19.0 | verified | 01443c1e1a29e531… |
| armhf | FerretDB | wekan/FerretDB | v1.49.0 | verified | 144404fb9793dc8e… |
| armhf | Node.js | wekan/node-patches | v24.19.0 | verified | b55350f3071b765a… |
| armv6 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 7c27b2c15448709a… |
| armv6 | Node.js | wekan/node-patches | v24.19.0 | verified | 128ded0cda638c1f… |
| armv7 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 144404fb9793dc8e… |
| armv7 | Node.js | wekan/node-patches | v24.19.0 | verified | 8dbe0a9aa8550ad5… |
| i386 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 1f70cb1687411b2a… |
| i386 | Node.js | wekan/node-patches | v24.19.0 | verified | 3b0b3bbfe27daf58… |
| mac-arm64 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 576364db59dfce3b… |
| mac-arm64 | Node.js | nodejs.org | v24.19.0 | verified | 3f1cf157479c1480… |
| mac-x64 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 37d70cd90aad6d38… |
| mac-x64 | Node.js | nodejs.org | v24.19.0 | verified | d35e95230f46f6f0… |
| ppc64le | FerretDB | wekan/FerretDB | v1.49.0 | verified | 7c61d4853d5163ad… |
| ppc64le | Node.js | nodejs.org | v24.19.0 | verified | c510c6ce12f07010… |
| riscv64 | FerretDB | wekan/FerretDB | v1.49.0 | verified | bd4912da70f5e6c1… |
| riscv64 | Node.js | unofficial-builds.nodejs.org | v24.19.0 | verified | cd1f14af28121480… |
| s390x | FerretDB | wekan/FerretDB | v1.49.0 | no checksum published | — |
| s390x | Node.js | nodejs.org | v24.19.0 | verified | a4792e65962ffa0a… |
| win-arm64 | FerretDB | wekan/FerretDB | v1.49.0 | verified | 792166623e774b0a… |
| win-arm64 | Node.js | nodejs.org | v24.19.0 | verified | 8502f4a50b458d4c… |
| win64 | FerretDB | wekan/FerretDB | v1.49.0 | verified | f42c50aa84095a96… |
| win64 | Node.js | nodejs.org | v24.19.0 | verified | 57f71ab3652e797d… |
A row saying no checksum published is not a failed check - it is a source that publishes nothing to check against. Those are the ones worth fixing at the source.
v10.83 2026-08-11 WeKan ® release
In short: a CRITICAL SECURITY ISSUE, PassBleed: the single-card
Excel export authorised against the board named in the URL and then read the
card named in the URL, with nothing tying the two together. Any authenticated
user could create their own public board, name it as the board, and export any
card from any private board on the instance - including the bytes of its image
attachments. The identically shaped PDF route had always resolved its card
correctly, which is what showed this was an omission rather than a decision, and
it is what the Excel exporter now does. It also fixes broken avatar images,
seen after upgrading from v6 but never actually working: the route that serves
them asked Meteor.userId(), which throws in a plain HTTP handler rather than
answering “nobody”, and the handler turned that into a 500 - and, once that was
fixed, that the same route had always ignored the boardId the client appends
so a public board can show its members’ pictures to visitors. The binaries
below are v10.82’s: nothing here rebuilds them.
| Platform | Binary | From | Version | SHA256 |
|---|---|---|---|---|
| amd64 | Node.js | nodejs.org | v24.19.0 | 14b342e71204f811bde6153be8e04b62aef63c236fef92b55f9c83154b409647 |
| amd64 | FerretDB | wekan/FerretDB | v1.48.0 | 2737687fd29a8a761cd960e45f300b68cf7b4a87d50c4cc5280bcbd42b6aa163 |
| arm64 | Node.js | nodejs.org | v24.19.0 | 01443c1e1a29e531ccad5a46fefa6df490d2189c49f7955904aecdbb0fe86fdc |
| arm64 | FerretDB | wekan/FerretDB | v1.48.0 | 5ae705dd49515a4ecd4e295c3b9aa4f3b454fad78613ec60fb99316bd7c34e3f |
| loong64 | Node.js | unofficial-builds.nodejs.org | v24.19.0 | c24f224726f2d785bd18a1fd09f5e6d1fecf0269928451a60c5da9eac8e92e68 |
| loong64 | FerretDB | wekan/FerretDB | v1.48.0 | 06ec86263455a7b598d22a87df0e044ea73ab5a3b72e96ad12ebed03c1374ac2 |
| mac-arm64 | Node.js | nodejs.org | v24.19.0 | 3f1cf157479c1480352083105e13faf9d008ede98e7e157746b6df940d197b94 |
| mac-arm64 | FerretDB | wekan/FerretDB | v1.48.0 | 9b15f4c10e473cd0a2c4feb4cb43e18042bd60c7035ec66cab3cfbe13edaabab |
| mac-x64 | Node.js | nodejs.org | v24.19.0 | d35e95230f46f6f0751df497c56622c6735e05d5e1fb1630996a005b9d328fe4 |
| mac-x64 | FerretDB | wekan/FerretDB | v1.48.0 | 4e188246dfa33bccef4cdd86701bc498b037cb3e91f579ff0dccb93aa0ef03ad |
| ppc64le | Node.js | nodejs.org | v24.19.0 | c510c6ce12f07010f771e6edb22a3fe23f4f2e6f40b1ffd4941aed0646a0d8b3 |
| ppc64le | FerretDB | wekan/FerretDB | v1.48.0 | 0400cd6dfc3d10d987a0fe80d75baa86c03c19170770fa2e602c92d558c3cfa6 |
| riscv64 | Node.js | unofficial-builds.nodejs.org | v24.19.0 | cd1f14af2812148002f58b58a5f9af512a50e3b8e8c148e0db44019dcb68edfd |
| riscv64 | FerretDB | wekan/FerretDB | v1.48.0 | d37c35af988670b9ed182b8c5966c06a06362f6c6ace6aebd93ccdfa32c9a26b |
| s390x | Node.js | nodejs.org | v24.19.0 | a4792e65962ffa0af42627aacf1122a60c3c88dbf4e4184f06820d66f9da8ba4 |
| s390x | FerretDB | wekan/FerretDB | v1.48.0 | 6c7d61fbb8c79b2e8733be8f71910f710e8c5cd25208c451bdc513c8313b0340 |
| win64 | Node.js | nodejs.org | v24.19.0 | 57f71ab3652e797d84acddc79c81cc9ff1c6ddb2a1974cdb83f00fee9bff4c73 |
| win64 | FerretDB | wekan/FerretDB | v1.48.0 | ea57e1bcd153b51d2065ab01515b21ec05d8f615444c15603ab8158b8a661dd2 |
This release fixes the following CRITICAL SECURITY ISSUE of PassBleed:
The single-card Excel export - which card it is allowed to read.
PassBleed: the export authorised against one board and read a card from another. Thanks to TWPaMWang and xet7.
PassBleed -
GHSA-6p5m-f9p2-wqm5,
Moderate, CWE-639, CVSS 6.5. GET /api/boards/:boardId/lists/:listId/cards/:cardId/exportExcel checked whether
the caller could see the board in :boardId, then resolved the card by
:cardId alone. Nothing confirmed that the card was on that board, so the two
identifiers came apart: one decided the authorisation, the other decided the
data.
The pass is self-service. POST /api/boards takes permission straight from
the request body, so any authenticated user could mint their own PUBLIC board,
name it as :boardId, and pass the id of a card in somebody else’s private
board as :cardId. :listId was never used in a query at all and could be any
string.
What came back was the card: title, full description, members and assignees,
every comment with its author, checklists and checklist items, subtask titles,
attachment metadata - and, because image attachments are read through
getReadStream() and embedded with workbook.addImage, the attachment BYTES.
The same board could be reused while :cardId was substituted, which made it a
scriptable bulk read rather than a single disclosure. The REST API is on by
default in the shipped Docker configuration.
The fix was already in the codebase one file away: the identically shaped PDF
route has always resolved getCard({ _id, boardId, listId }) and 404s a
cross-board id. That control is what shows the Excel exporter’s omission was a
defect rather than a decision, and it is what the Excel exporter now does.
Constraining the QUERY matters more than a check after it - the exporter fans
out on the same card id for checklists, subtasks, comments and attachments, none
of which carry a board constraint of their own, so a card that cannot resolve
outside the authorised board makes all of them safe by construction.
The route binds the two identifiers as well, before either branch builds - deliberate duplication, because that is where both arrive together and it covers the public-board branch, which skips authentication entirely. A card that is not on the named board is a 404 rather than a 403, so the difference does not reveal whether a card id exists.
and fixes the following bugs:
Avatars - the routes that serve a profile picture, and who they serve it to.
Ask the request who it is, because Meteor.userId() cannot. Thanks to markusst1982 and xet7.
Following the same upgrade as #6583, profile pictures came back as broken images - initials rendered fine, and the Admin Panel showed a user’s picture while a board showed the missing-picture icon for the same person.
Nothing was lost, and the migration is not at fault. The avatar files migrate,
and the Meteor-Files record made from a CollectionFS filerecord even reuses its
_id, so a 6.x URL still names the right object. What broke is the request for
it. A 6.x install stores profile.avatarUrl as /cfs/files/avatars/<id>; that
route serves the legacy bytes if they are still there and otherwise redirects to
/cdn/storage/avatars/<id>, which asked who was asking with Meteor.userId().
That reads the current DDP invocation’s environment, which exists inside a
method or a publication and NOT in a WebApp handler - where it does not return
“nobody”, it THROWS. The handler wraps its body in a try/catch that answers
500, so the throw was swallowed into a broken image, and no avatar served
through that route ever reached anybody on any install. The upgrade did not
cause it; it moved every avatar URL onto the route where it already applied.
server/routes/legacyAttachments.js had the identical call, so legacy
attachment URLs failed the same way.
An HTTP request carries its identity in the request: a bearer token, an
X-Auth-Token header, an ?authToken= parameter, or the login cookie - and on
Sandstorm, a platform-injected user id and no Meteor token at all.
server/routes/universalFileServer.js has always resolved it that way and
serves attachments correctly today. server/lib/requestUser.js lifts that
resolution out so the two routes that were guessing share it rather than grow a
third copy. It never throws: a caller deciding whether to serve a file wants an
answer, not an exception its own catch will turn back into a 500.
tests/requestUserAuth.test.cjs pins that neither route calls
Meteor.userId(), that both await the resolver - an unawaited Promise is
truthy and would authorise everybody - that all four token carriers and the
Sandstorm path are handled, and that the migration still reuses the id the old
URL names. Confirming the served image needs an upgraded instance.
Honour the boardId parameter the client has been sending all along. Thanks to markusst1982 and xet7.
Found while checking why the Admin Panel showed a picture that a board did not.
The two URLs differ in one thing: the avatarUrl helper in
client/components/users/userAvatar.js appends ?boardId=<id>, and says why in
its own comment - “so public viewers can access avatars on public boards”. The
Admin Panel uses profile.avatarUrl raw.
/cdn/storage/avatars/:fileName never read that parameter. It required a
signed-in user and nothing else, so on a public board every visitor who was not
logged in got a 401 and the missing-picture icon - the exact case the parameter
was added for. Fixing Meteor.userId() alone would have left that half broken.
The named board must now exist, be public, AND have the avatar’s owner as a member. The last part is not ceremony: without it, naming any public board would unlock any avatar on the instance, and a public board publishes its own members, not everybody.
The legacy redirect keeps the query string too. /cfs/files/avatars/<id> 301s
to /cdn/storage/avatars/<id>, and that is the path EVERY migrated 6.x avatar
URL takes, so dropping ?boardId= there would 401 exactly the installs the
entry above sets out to fix.
Thanks to above GitHub users for their contributions and translators for their translations.