Skip to content

v11.65

Choose a tag to compare

@github-actions github-actions released this 09 Sep 16:51
· 7 commits to main since this release

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),
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
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
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
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.