Binaries 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.78.0 | verified | 523a96e832e5947a… |
| amd64 | Node.js | nodejs.org | v24.21.0 | verified | fd8e59d5a511510f… |
| arm64 | FerretDB | wekan/FerretDB | v1.78.0 | verified | d8bb85c7ff49fe02… |
| arm64 | Node.js | nodejs.org | v24.21.0 | verified | 6ad1325edbdb5649… |
| armhf | FerretDB | wekan/FerretDB | v1.78.0 | verified | c4df2f4e6fe8fa9a… |
| armhf | Node.js | wekan/node-patches | v24.20.0 | verified | ace678ca4601db06… |
| armv6 | FerretDB | wekan/FerretDB | v1.78.0 | verified | eeb962ba8d7b76d7… |
| armv6 | Node.js | wekan/node-patches | v24.20.0 | verified | e01021ab2ddd42cd… |
| armv7 | FerretDB | wekan/FerretDB | v1.78.0 | verified | c4df2f4e6fe8fa9a… |
| armv7 | Node.js | wekan/node-patches | v24.20.0 | verified | a227473dc166e862… |
| i386 | FerretDB | wekan/FerretDB | v1.78.0 | verified | c855b2f74a7c8b13… |
| i386 | Node.js | wekan/node-patches | v24.20.0 | verified | a90b92e80d95c341… |
| mac-arm64 | FerretDB | wekan/FerretDB | v1.78.0 | verified | 34d45b3eee2f322f… |
| mac-arm64 | Node.js | nodejs.org | v24.21.0 | verified | 6239d4cf92d86448… |
| mac-x64 | FerretDB | wekan/FerretDB | v1.78.0 | verified | 1fd4a358aae472d9… |
| mac-x64 | Node.js | nodejs.org | v24.21.0 | verified | 0ae5a24c24bb7d01… |
| ppc64le | FerretDB | wekan/FerretDB | v1.78.0 | verified | ae5e77d7e26ff668… |
| ppc64le | Node.js | nodejs.org | v24.21.0 | verified | 1936fd64623a2f98… |
| riscv64 | FerretDB | wekan/FerretDB | v1.78.0 | verified | c52b5d9b477d8a73… |
| riscv64 | Node.js | unofficial-builds.nodejs.org | v24.21.0 | verified | 5c4e83d46cc1f8ee… |
| s390x | FerretDB | wekan/FerretDB | v1.78.0 | verified | 5f6e44510345e653… |
| s390x | Node.js | nodejs.org | v24.21.0 | verified | 2ef7e2ecbf7a6c2f… |
| win-arm64 | FerretDB | wekan/FerretDB | v1.78.0 | verified | ebd8eb6dac62319d… |
| win-arm64 | Node.js | nodejs.org | v24.21.0 | verified | 8779b1bde1d39f8d… |
| win64 | FerretDB | wekan/FerretDB | v1.78.0 | verified | 39b8bd8b95754497… |
| win64 | Node.js | nodejs.org | v24.21.0 | verified | 158f7685b44de51f… |
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.
v11.65 2026-09-09 WeKan ® release
In short: Four security advisories against Attachments/Avatars
(ostrio:files) are fixed: a critical path-traversal arbitrary file
write via the attachment upload namingFunction, a critical
unauthenticated DDP method that could wipe every attachment or avatar on
the instance, and two high missing-authorization bugs that let an
anonymous caller download any avatar (a missing protected callback,
and an unauthenticated legacy-avatar route). The AppImage no longer
mounts itself under a possibly-small /tmp, relocating to
WRITABLE_PATH/app instead.
This release fixes the following CRITICAL SECURITY ISSUES:
Unauthenticated Arbitrary File Write via Path Traversal in Attachment Upload namingFunction. Thanks to xet7.
Attachments overrode ostrio:files' `sanitize()` to an identity function and used the client-supplied `fileId` verbatim as the on-disk file name in `namingFunction`, so an anonymous upload with `fileId: "../../../../tmp/pwn"` could write attacker-controlled content anywhere the WeKan process can write - including overwriting bundle modules for remote code execution. `sanitize()` is restored to the same whitelist `models/avatars.js` already used for the same tokens (file DISPLAY names are untouched - they go through a separate, unrelated sanitizer in `onBeforeUpload`), and `namingFunction` now also validates the sanitized `fileId` against the ObjectId shape WeKan itself generates, regenerating a fresh one rather than trusting it. A blocked attempt is recorded through the shared security log (`authz.upload-path`/[UploadPathBleed](https://wekan.fi/hall-of-fame/uploadpathbleed/)), so Admin Panel / Problems shows it happened. `tests/attachmentAvatarSecurityAdvisories.test.cjs` pins both the restored sanitizer and the fileId validation, with the advisory's own PoC string as a negative case.Unauthenticated DDP Methods Allow Instance-Wide Deletion of Attachments and Avatars. Thanks to xet7.
ostrio:files registers its own `_FilesCollectionRemove_<collection>` DDP method, gated only by `allowClientCode` and never routed through `Attachments.allow`/`Avatars.allow` - those only gate the ordinary Mongo `.remove()` call, not the library's own method. Attachments had no `onBeforeRemove` at all, and Avatars' unconditionally returned `true` (it existed only to clear the removed avatar's owner's `profile.avatarUrl`), so any anonymous DDP connection could call either method with selector `{}` and delete every attachment (database record and physical file) or every avatar on the instance. Both now require `this.userId` and check every file the selector actually matches: attachments need the caller's board-write access on that file's card/ board, avatars need ownership of that avatar or site-admin status (the existing admin "delete another user's avatar" flow keeps working). A blocked attempt is recorded through a new `authz.file-remove`/[WipeBleed](https://wekan.fi/hall-of-fame/wipebleed/) catalog key. `tests/attachmentAvatarSecurityAdvisories.test.cjs` pins both hooks and that an empty/non-matching selector is refused outright rather than treated as nothing to check.and fixes the following bugs:
Avatars - anonymous access to files nothing should have exposed.
Add the protected callback the download library needs to gate them. Thanks to xet7.
Unlike Attachments, Avatars never set `protected`, so ostrio:files' own library-native download route - whose `_checkAccess` defaults to allowing everything when `protected` is unset - served any avatar to any anonymous caller, entirely bypassing WeKan's own `isAuthorizedForAvatar` check. `Avatars.protected` now mirrors `Attachments.protected`: an authenticated caller may always view an avatar; an anonymous one only when the avatar's owner is a member of a public board. A denied anonymous download is recorded under a new `authz.avatar-protected`/[PortraitBleed](https://wekan.fi/hall-of-fame/portraitbleed/) catalog key.serveLegacyAvatar Serves Legacy CollectionFS Avatars Without Any Authentication. Thanks to xet7.
Both routes in `server/routes/avatarServer.js` that fall back to reading a legacy CollectionFS avatar in place streamed it to any caller who knew its old `cfs.avatars.filerecord` id - one of the two (`/cfs/files/avatars`) with no authentication check at all. Both now require a signed-in caller (`isLegacyAvatarAuthorized`): legacy records carry no owner/board link that could be safely checked for the public-board exemption current avatars get, so this is a deliberately narrower rule rather than reusing that exemption on an unverifiable claim. The `/cfs/files/avatars` route's redirect fallback for already-migrated avatars is untouched, so an anonymous public-board viewer still sees those normally - only the legacy read-in-place path now requires a login. A denied attempt is recorded under a new `authz.legacy-avatar`/[RelicAvatarBleed](https://wekan.fi/hall-of-fame/relicavatarbleed/) catalog key. `tests/attachmentAvatarSecurityAdvisories.test.cjs` pins both call sites and the negative case that the redirect still works unauthenticated.and fixes the following bug:
AppImage - its own mount filling up a small /tmp.
Relocate the AppImage's own mount from /tmp to WRITABLE_PATH/app. Thanks to xet7.
checkmk warned `/tmp/.mount_wekan.OhaGOG ... 100% used` because the AppImage runtime's own read-only squashfs mount landed on a small `/tmp` - a squashfs mount always reports itself as 100% used regardless of size, so this was really "`/tmp` is too small for the AppImage", not a leak. The runtime mounts itself under `$TMPDIR/.mount_<name>.<random>` (defaulting to `/tmp`) before `AppRun` ever runs, so the very first launch's mount cannot be redirected from inside `AppRun`. `AppRun` now re-execs itself once per launch with `TMPDIR` set to `WRITABLE_PATH/app` when the caller has not already chosen a `TMPDIR`, so every launch from then on mounts there instead - and, on that same first launch, sweeps out any of WeKan's own orphaned `.mount_*ekan*` directories left in `/tmp` by an earlier, uncleanly killed run (checked against `/proc/mounts`, so a live one is never touched). AppImage-only: no other WeKan platform mounts itself this way, so Docker, snap, the `.deb` and the bundle zip are untouched. `tests/appImageRuntime.test.cjs` pins the relocation, its once-per-launch/explicit-`TMPDIR` guards, and that only orphaned mounts are removed.and has the following developer-tooling fixes:
Fix [#3823] e2e test for the Show on Minicard -> Board Settings/Card move. Thanks to xet7.
The test still clicked the minicard's own "Show on Minicard" menu entry (`.js-show-on-minicard`), which no longer exists after the Board Settings / Card move earlier in this release: the checkbox (`.js-field-has-creator-on-minicard`) and its behavior are unchanged, so the test now opens it from Board Settings / Card, reached from the board's cog menu, instead.Update hardcoded SQLite version/source-id pins to 3.53.4. Thanks to xet7.
The `modernc.org/sqlite` bump (1.57.0 → 1.58.0, from the earlier "ferretdb" dependabot group update) embeds a newer SQLite release (3.53.3 → 3.53.4), which three tests pinned by exact string: `TestDefaults` in `internal/backends/sqlite/metadata/pool/pool_test.go` (`sqlite_version()`/`sqlite_source_id()`), and the `BackendVersion` checks in `internal/backends/backend_test.go` and `internal/backends/sqlite/metadata/registry_test.go`. The dependency bump is the intended change; the guards are updated to match it.Thanks to above GitHub users for their contributions and translators for their translations.