Hall of Fame image from https://openclipart.org/detail/120343/trophy
Back to WeKan Website

Contents

See SECURITY.md how to do Responsible Security Disclosure by email to security@wekan.fi

CVE Icon Vulnerability name Date Responsible Security Disclosure by Stars Process Vulnerabilities
GHSA-6p5m-f9p2-wqm5

PassBleed 2026-08-11 TWPaMWang and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-6p5m-f9p2-wqm5.
Details
  • PassBleed — the single-card Excel export authorised against one identifier and read its data using another. 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, with nothing tying the two together (CWE-639 Authorization Bypass Through User-Controlled Key, CVSS 6.5)
  • So :boardId became a reusable ACCESS PASS and :cardId alone decided what came back. 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. :listId was never used in a query at all and could be any string
  • The workbook that came back carried the victim card's 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. One board could be reused while :cardId was substituted freely, which made it a scriptable bulk read rather than a single disclosure
  • The same route shape for PDF had always been right: ExporterCardPDF resolves getCard({ _id, boardId, listId }) and returns 404 for a cross-board id. That control in the same codebase is what shows this was an omission rather than a decision, and it is the fix — the Excel exporter now uses the same constrained lookup, so a card outside the authorised board does not resolve at all and the checklist, subtask, comment and attachment fan-out keyed on that card id can reach nothing. The route binds the two identifiers as well, before either branch builds, including the public branch that skips authentication entirely
  • Fixed at upcoming WeKan release
  • More details
GHSA-phm4-4v26-j2vq

WhereBleed 2026-08-11 TungNGo02 and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-phm4-4v26-j2vq.
Details
  • WhereBleed — eight Admin Panel handlers took a MongoDB query selector from the client and validated only its TYPE: check(query, Match.OneOf(Object, null)). That is not validation, because a selector is executable data — $where makes the database run the caller's JavaScript once per document scanned (CWE-943 Improper Neutralization of Special Elements in Data Query Logic, CVSS 5.8)
  • The surfaces: the people, org, team and translation publications and their companion *CollectionCount / getPeoplePageIds methods. Meteor.subscribe('team', { $where: 'while(true){}' }, 25, 0) pins a database worker for as long as the caller likes and is repeatable — denial of service for every tenant on the instance. Demonstrated on v10.81 against a real MongoDB 7: $where: 'sleep(2000) || true' made the subscription take 2.03s and return the document, $where: 'false' returned nothing in 0.00s, which is the caller deciding in JavaScript which documents come back
  • It needs an authenticated admin session, so no board member or visitor can reach it. It matters at this severity because the people and org surfaces are open to a PER-TENANT Global Admin — a role meant to be confined to one Organization — and those two wrap the caller's selector as { $and: [query, restriction] } rather than stripping execution operators out of it, so merging the tenant restriction never removed the $where
  • What makes this one particular is that the defence was ALREADY in the codebase. classifySelector and hasWhere were written for exactly this class, are unit-tested, and were wired into the card-window publication; the eight siblings simply never called them. So the fix adds no new detection logic — that publication's own helper moved unchanged into server/lib/selectorGuard.js and all nine call sites share the one copy, because a second copy would be the same bug set up to happen again. Each refuses with the "match nothing" selector the card window already used in production, so a refused request returns an empty result rather than throwing at an admin mid-page, and ordinary searches, filters and paging are unaffected
  • FerretDB, WeKan's default database, rejects $where itself, so this degrades to a rejected query there; the supported MongoDB path is where it was reproduced
  • Fixed at upcoming WeKan release
  • More details
GHSA-4mxf-m8pq-xc9p

PathBleed 2026-08-09 Alpastx and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-4mxf-m8pq-xc9p.
Details
  • PathBleed — an avatar's owner could write the ON-DISK PATH of their own avatar. Attachments refused client-supplied versions.*.path; avatars did not, because that guard was written inside the attachment permission file and never copied. The whole avatar update rule was update: isOwner, which says WHOSE document may change and nothing about WHICH FIELDS (CWE-22 Path Traversal, CWE-73 External Control of File Name or Path)
  • Board export then read it: for every member whose avatar is a local WeKan file the exporter opens versions.original.path and embeds the bytes as base64 in profile.avatarFile. Point your own avatar at /etc/passwd — or anything under WRITABLE_PATH — export a board you are a member of, decode the JSON: arbitrary file read as the WeKan OS user, from any account that can own an avatar. The CDN download path was separately guarded; export was not
  • Fixed at both ends. The WRITE: the three guards now live in models/lib/fileVersionFields.js and BOTH permission files import them, so avatars refuse a versions payload on insert, refuse any update touching the versions subtree, and keep to the same field whitelist — ownership still required, no longer sufficient. The READ: nothing is read from a stored path unless it RESOLVES inside WeKan's own storage (models/lib/storagePathContainment.js), which also holds for a path poisoned by an old document, a restored backup or a bad migration. The download path's private copy of that check is gone, so download and export ask the same question
  • Fixed at upcoming WeKan release
  • More details
GHSA-jvv9-498p-hxrg

ParentBleed 2026-08-09 Alpastx and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-jvv9-498p-hxrg.
Details
  • ParentBleed — a card's parentId may name a card on ANOTHER board, and setting it was authorized only against the CHILD board's write access. Nothing asked whether the person setting it, or the people subscribed to the child board, were allowed to see the other board (CWE-862 Missing Authorization)
  • The board publication walks the whole ancestor chain, because the prefix-with-full-path subtask setting renders a subtask's complete path, and it published the complete ancestor card DOCUMENTS to every subscriber of the child board. Write access on shared board B plus one card id from private board A therefore delivered A's card — title, description, custom fields — over DDP to people with no part in A (CWE-200 Exposure of Sensitive Information)
  • Fixed at both ends. The WRITE refuses a parent whose board the actor cannot see, asked in one place with the same selectors the publication and All Boards use — so an ACTIVE org/team/domain share counts and a revoked one does not — enforced on REST create, REST update and a DDP deny rule covering insert as well as update. The PUBLICATION sends only the ancestors whose board the subscriber may see; the board being published is its own answer, so an ordinary same-board subtask path is unchanged. It is the read check the linked-card path already made, applied to the field that lacked it
  • Fixed at upcoming WeKan release
  • More details
GHSA-gwc4-fw7p-gw58

RevokeBleed 2026-08-09 Alpastx and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-gwc4-fw7p-gw58.
Details
  • RevokeBleed — isActive: false is how a board admin REVOKES a share with an organization, a team or an email domain, and the board publication never looked at it. All Boards asked correctly, with $elemMatch; the publication had its own copy written as 'orgs.orgId': { $in: [...] }, and a dotted path matches an array element without saying anything about that element's other fields (CWE-639 Authorization Bypass Through User-Controlled Key, CWE-863 Incorrect Authorization)
  • So the board vanished from the revoked user's All Boards — which is what the admin saw and believed — while a subscription by a boardId they still remembered returned the whole private board: document, lists, swimlanes, cards, comments, attachments. A revoke the primary data publication does not honour is not a revoke. The same applied to team and domain shares
  • Fixed by writing the rule once: models/lib/boardVisibilitySelectors.js builds the $or, both Boards.userBoards and the board publication call it, and every share kind is matched with $elemMatch requiring isActive: true. The one clause that is not a relationship to the user — { permission: 'public' } — stays optional, so the boards list still shows public boards and the search over all boards still excludes them
  • Fixed at upcoming WeKan release
  • More details
GHSA-pqr4-rxgp-hv2m

CommentBleed 2026-08-09 Alpastx and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-pqr4-rxgp-hv2m.
Details
  • CommentBleed — DELETE /api/boards/:boardId/cards/:cardId/comments/:commentId checked board MEMBERSHIP only, so any normal member could delete any other user's comment on the board (CWE-639 Authorization Bypass Through User-Controlled Key, CWE-863 Incorrect Authorization)
  • The author-or-admin rule, and the board's restrictCommentEditing setting, were enforced in a collection hook that decides from the Meteor userId — with an early return for the genuine server-internal callers (board copy, cleanup, migrations) that run with no user. An HTTP request is not one of those, but carries no Meteor userId either, so the removal landed on that trusted path: HTTP 200, somebody else's comment gone, on a restricted board, while the same deletion over DDP was correctly refused
  • Fixed by asking the question where the answer is known: the handler loads the comment (404 when there is none) and applies the same rule itself, with req.userId, before removing anything, answering 403 when it says no. That rule is now an exported function the hooks and the handler both call, so DDP and HTTP cannot enforce different things. The no-userId path stays, documented for the internal callers it was written for
  • Fixed at upcoming WeKan release
  • More details
-

PatternBleed 2026-08-08 GitHub CodeQL (code scanning alert #431) and xet7
Process Automated code scanning flagged the identity (no-op) replacement.
Details
  • PatternBleed — an escape that escaped nothing. A platform name was interpolated into a regular expression through p.replace('-', '-'), which replaces a hyphen with a hyphen: it reads as “escape this before putting it in a pattern” and does nothing at all, so the value went in raw (CWE-116 Improper Encoding or Escaping of Output)
  • GitHub CodeQL code scanning alert #431, rule js/identity-replacement, severity Medium
  • Nothing failed, because a hyphen outside a character class needs no escaping — but the guard it looked like was not there, and a platform name carrying a . or a + would have matched the wrong row or thrown. Test-only code (tests/releaseNodeSources.test.cjs) over a hardcoded list, so no runtime exposure
  • Fixed by escaping the value for real, with the same escapeRegExp the other guards in tests/ use. Being the SECOND finding of this rule after IdentityBleed (alert #424), the fix also adds tests/noIdentityReplacement.test.cjs, which catches the whole class in WeKan's own test run rather than after a push
  • Fixed at upcoming WeKan release
  • More details
GHSA-2g94-9x3m-hv37

LockoutBleed 2026-08-04 NinjaGPT and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-2g94-9x3m-hv37.
Details
  • LockoutBleed — user enumeration chained with unthrottled password brute-force into account takeover. The bundled wekan-accounts-lockout (default 3 failures → 60 s lockout) was completely inert: its two Accounts.validateLoginAttempt hooks decided whether an attempt failed by comparing the error's REASON STRING (reason !== 'Incorrect password' for a known user, !== 'User not found' for an unknown one), but Meteor's ambiguousErrorMessages (on by default) rewrites every credential failure to one generic sentence BEFORE those hooks run. The literals never matched, both hooks returned early, the counter never incremented, and no account ever locked — unlimited unthrottled guessing (CWE-307 Improper Restriction of Excessive Authentication Attempts)
  • The same login path leaked WHICH ACCOUNTS EXIST by timing: accounts-password runs a bcrypt comparison (~50 ms) only for a user that exists and has a local password, and returns in ~2 ms otherwise. The distributions do not overlap, so an unauthenticated attacker classifies any username or email as real or not with near-100% accuracy, regardless of the uniform error text (CWE-208 Observable Timing Discrepancy / CWE-204). The REST POST /users/login twin was worse: it threw a distinct “User with that username or email address not found.” for a missing user and never went through the lockout hooks at all
  • Fixed by deciding lockout from the attempt's STRUCTURAL fields instead of a localized Meteor-internal string (new packages/wekan-accounts-lockout/src/loginFailureDecision.js), so any genuine password failure is counted and the lockout fires — while the benign no-2fa-code step (password already correct, second factor still to come) is never counted, so 2FA users are not locked out of their own sign-in
  • The enumeration timing is equalised with one DUMMY BCRYPT COMPARISON against a fixed cost-10 hash whenever the real path would skip bcrypt (server/lib/loginTimingDefense.js), wired into the DDP login method by a normalization handler that runs ahead of the built-in one and never authenticates (server/loginTimingNormalization.js). The REST endpoint now answers missing-user and wrong-password IDENTICALLY, runs the same equaliser, and THROTTLES failed attempts per client address (server/lib/loginAttemptThrottle.js) — only failures count and a success clears the counter
  • Fixed at upcoming WeKan release
  • More details
GHSA-j9p2-jm73-p549

FollowBleed 2026-08-03 RandomGenerator and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-j9p2-jm73-p549.
Details
  • FollowBleed — a redirect walked the import downloads past the SSRF guard. The live Trello import (server/trelloApiImport.js) DID validate the attachment URL with validateAttachmentUrl() — the fix that closed LiveBleed / CVE-2026-30844 — and then downloaded it with the platform fetch(), which FOLLOWS REDIRECTS. So the guard only ever saw the request, and the target gets to answer: a public URL passes validation, that host replies 302 Location: http://127.0.0.1:18080/secret, and the loopback response body is stored as the imported attachment and read back through WeKan. Non-blind SSRF against loopback services, internal admin panels, cloud metadata and anything else reachable from the container (CWE-918 Server-Side Request Forgery)
  • A guard on the URL alone cannot hold, because the target gets to answer and an answer can name a new URL. fetchSafe() (server/lib/ssrfGuard.js) now guards EVERY HOP: maxRedirects defaults to 0, which refuses any 3xx outright as before — right for outgoing webhooks and avatar downloads, because a legitimate one never redirects — and a caller that must follow one passes a small number, each hop going through the same protocol allowlist, blocked-range check and DNS pinning as the original URL before a packet is sent to it. Credentials are dropped on a cross-origin redirect, so following Trello's 302 to S3 cannot hand the API key and token to whoever the redirect names
  • Refusing every redirect was not an option: Trello's own attachment endpoint answers with a 302 to a signed S3 URL, so that would have meant importing no attachments at all
  • The OFFLINE importers had the same hole and were not in the report: they handed the validated URL to Meteor-Files' Attachments.loadAsync(), which downloads with the platform fetch() too, so a pasted Trello or WeKan board export reached 127.0.0.1 by exactly the same 302. They download through the guard now
  • Fixed at upcoming WeKan release
  • More details
GHSA-c5xr-mg26-vq5w

TransitBleed 2026-08-03 tonghuaroot and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-c5xr-mg26-vq5w.
Details
  • TransitBleed — IPv6 transition addresses walked straight through the SSRF block-list. isIpBlocked() in models/lib/attachmentUrlValidation.js is the ONE block-list behind both halves of the defence — the input-time validator and the delivery-time guard fetchSafe() — and its IPv6 half classified an address by its SPELLING: startsWith('::ffff:'), startsWith('2001:db8'), and the first hextet parsed out of the string. IPv6 has several standard ways to write “this packet goes to an IPv4 address” and none of them looks like ::ffff: (CWE-918 Server-Side Request Forgery)
  • The forms that passed: 2002:a9fe:a9fe:: — 6to4 (RFC 3056) → 169.254.169.254; 64:ff9b::c0a8:101 — NAT64 (RFC 6052) → 192.168.1.1; 2001:0:… — Teredo (RFC 4380), the IPv4 stored as the complement of the low 32 bits; and even 0:0:0:0:0:ffff:7f00:1, a plain IPv4-mapped 127.0.0.1 merely spelled out. On a host with a 6to4 relay or a NAT64 gateway — ordinary in cloud and Kubernetes networks — the packet arrives at that IPv4 address, so http://[2002:a9fe:a9fe::]/latest/meta-data/ read cloud metadata through the guard whose whole job was to stop it
  • Fixed by EXPANDING the address to its 16 bytes once and reading those bytes, so notation cannot change the answer, and extracting the embedded IPv4 from every transition form to re-check it with the IPv4 rules: 6to4, NAT64 (the well-known prefix and the RFC 8215 local-use one), Teredo through both its server and its obfuscated client address, IPv4-mapped, IPv4-translated, IPv4-compatible, and ISATAP under any routing prefix rather than only the link-local one. The deprecated fec0::/10 site-local range is blocked too
  • A transition address wrapping a PUBLIC IPv4 is still allowed, and the tests pin that as carefully as they pin the bypasses: a guard that blocks everything is a guard somebody switches off
  • Fixed at upcoming WeKan release
  • More details
CVE-2026-68901 GHSA-3gcg-g6rf-w2rx

CrashBleed 2026-07-26 laijunyue and xet7
Process Coordinated disclosure via GitHub Security Advisory GHSA-3gcg-g6rf-w2rx.
Details
  • CrashBleed — remote denial of service: an invalid authToken on a board export endpoint crashed the whole server. The board export REST endpoints look a user up by the login token in ?authToken=. A token that matches nothing makes that lookup answer undefined, and the next line dereferenced it — user._id.toString() — throwing a TypeError out of an async route handler with no try/catch. That escapes as an unhandled promise rejection, which this app turns into a full process crash, so one crafted GET against a private board id took the server down for every user. Reachable by anyone who can obtain a private board id, which on an open-registration instance means anyone at all (CVE-2026-68901 GHSA-3gcg-g6rf-w2rx, CWE-476)
  • It was an incomplete fix: models/exportPDF.js and models/exportExcelCard.js already had the if (!user) guard; three handlers in models/export.js and one in models/exportExcel.js were missed
  • Fixed on both levels: every token lookup in the export models is now followed by that guard — 401 “Invalid token” and return — including the two handlers that did not crash because they hand the user to canExport() instead of dereferencing it; and every export route body is wrapped in safeRoute() (server/apiMiddleware.js), which awaits the handler, answers 500 once and logs the request that failed, so a throw from any other cause is one broken request instead of an outage
  • Affected Wekan v10.37 and earlier; fixed at Wekan v10.38 2026-07-26
  • More details
-

ZipBleed 2026-07-25 xet7
Process Found while reviewing the open dependency pull requests.
Details
  • ZipBleed — restoring a backup archive wrote entries wherever the archive told it to. A zip entry carries its own path and path.join() RESOLVES .. segments instead of rejecting them, and the restore in server/methods/backup.js checked only that an entry's first path segment was attachments or avatars. An entry named 2026-07-25_12-00-00/attachments/../../../../etc/cron.d/wekan passed that check — its first segment really is attachments — and joined its way out of the files directory, so a crafted backup.zip could drop or overwrite a file anywhere the WeKan process could write (CWE-22 Improper Limitation of a Pathname to a Restricted Directory, "zip-slip")
  • Reachable by an admin restoring an archive (restoreBackup is behind requireAdmin()), which is how a hostile archive arrives: offered as a backup to restore, at the moment nobody inspects the file they were handed
  • Fixed by resolving each entry to an absolute path and requiring it to sit under the directory it belongs in, compared against the base plus a separator so a sibling directory with a matching prefix (/data/files/attachments-evil) is refused too; the collection name in the data half of an archive is constrained to a plain name, which also keeps a restore out of the database's internal system.* collections
  • Fixed at upcoming WeKan release
  • More details
CVE-2026-68900 GHSA-8r5p-4q9j-f5jx

ExportBleed 2026-07-22 koyokr and xet7
Process Privately reported via GitHub Security Advisory GHSA-8r5p-4q9j-f5jx.
Details
  • ExportBleed — 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, but the HTML board exporter (client/lib/exportHTML.js) embedded a card-click handler that read the title/body via .textContent (which DECODES entities) and concatenated them into 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 revoked. Fixed by building the modal from DOM nodes and assigning the title/body via textContent, never innerHTML (CWE-79 Cross-site Scripting)
  • Reported privately by koyokr (https://github.com/koyokr) via GHSA-8r5p-4q9j-f5jx
  • Fixed at upcoming WeKan release
  • More details
-

RedirectBleed 2026-07-19 meifukun and xet7
Process Privately reported 8 issues reviewed against WeKan v9.95.0.
Details
  • RedirectBleed — avatar localization (server/lib/localizeAvatar.js) validated only the ORIGINAL URL host with assertSafePublicUrl and then fetched with native fetch(url, {redirect:'follow'}), so an authenticated user could set profile.avatarUrl to a public redirector that 302s to 127.0.0.1, a private network, or 169.254.169.254 and the WeKan server followed it (SSRF). Fixed by fetching through the DNS-pinned, redirect-rejecting fetchSafe and scheme-validating profile.avatarUrl at write time (CWE-918 Server-Side Request Forgery)
  • Reported privately by meifukun (https://github.com/meifukun)
  • Fixed at upcoming WeKan release
  • More details
-

SourceBleed 2026-07-19 meifukun and xet7
Process Privately reported 8 issues reviewed against WeKan v9.95.0.
Details
  • SourceBleed — a Trello board imported with a javascript: url had that URL stored as an activity source.url (models/trelloCreator.js) and rendered as an activity-sidebar link (client/components/activities/activities.js) with no scheme check, so a board admin who clicked the "Trello" source link ran attacker JavaScript in their session and could read Meteor.loginToken (stored XSS → account takeover). Fixed by only storing and linking http(s) source URLs (CWE-79 Stored Cross-site Scripting)
  • Reported privately by meifukun (https://github.com/meifukun)
  • Fixed at upcoming WeKan release
  • More details
-

LiveBleed 2026-07-19 meifukun and xet7
Process Privately reported 8 issues reviewed against WeKan v9.95.0.
Details
  • LiveBleed — the live Trello import (server/trelloApiImport.js) downloaded attacker-controlled Trello attachment / background / avatar URLs with bare fetch() — no SSRF guard, unlike the offline path — and stored the response as an imported attachment readable back through the attachment API, giving NON-BLIND SSRF (cloud metadata / internal services). Fixed by gating every live-import download with validateAttachmentUrl(), matching the offline import (CWE-918 Server-Side Request Forgery)
  • Reported privately by meifukun (https://github.com/meifukun)
  • Fixed at upcoming WeKan release
  • More details
-

CasBleed 2026-07-19 meifukun and xet7
Process Privately reported 8 issues reviewed against WeKan v9.95.0.
Details
  • CasBleed — with CAS login enabled, packages/wekan-accounts-cas/cas_server.js stored validated CAS user data in a single module-global _userData shared across concurrent logins. Two logins racing could bind an attacker's credential token to a victim's user data, issuing the attacker a session for the victim's account (full admin if the victim was an admin). Fixed by binding the validated CAS user data PER credential token (CWE-362 Race Condition → Account Takeover)
  • Reported privately by meifukun (https://github.com/meifukun)
  • Fixed at upcoming WeKan release
  • More details
-

MetricsBleed 2026-07-19 meifukun and xet7
Process Privately reported 8 issues reviewed against WeKan v9.95.0.
Details
  • MetricsBleed — the /metrics endpoint (models/server/metrics.js) trusted the client-supplied X-Forwarded-For header UNCONDITIONALLY when checking METRICS_ACCEPTED_IP_ADDRESS, so an unauthenticated requester could send X-Forwarded-For: <whitelisted-ip> and read operational Prometheus metrics (connected/registered user counts, board counts, active board titles). Fixed by trusting XFF only when METRICS_TRUST_PROXY is set (parsed spoof-resistantly from the right); otherwise the real socket peer address is used (CWE-290 Authentication Bypass by Spoofing)
  • Reported privately by meifukun (https://github.com/meifukun)
  • Fixed at upcoming WeKan release
  • More details
-

ImpersonateBleed 2026-07-19 meifukun and xet7
Process Privately reported 8 issues reviewed against WeKan v9.95.0.
Details
  • ImpersonateBleed — several board export endpoints (models/export.js, exportExcel.js, exportExcelCard.js, exportPDF.js) authorized export with canExport(user) || impersonateDone, where impersonateDone was merely the existence of ANY historical ImpersonatedUsers record for the user. A former admin who ever used impersonation kept permanent export access to any private board even after being demoted. Fixed by removing the impersonation bypass so export requires real board visibility (canExport) only (CWE-863 Incorrect Authorization)
  • Reported privately by meifukun (https://github.com/meifukun)
  • Fixed at upcoming WeKan release
  • More details
-

InviteBleed 2026-07-19 meifukun and xet7
Process Privately reported 8 issues reviewed against WeKan v9.95.0.
Details
  • InviteBleed — when public registration is disabled, invitation registration used a 6-digit code generated with Math.random() (~900,000 keyspace, non-cryptographic RNG; server/models/settings.js) with no throttling on the sign-up validation, so an attacker who knew a pending invitee's email could brute-force the code, claim the account and join its private boards. Fixed by generating a 128-bit crypto.randomBytes invitation code and rate-limiting createUser with DDPRateLimiter (CWE-330 Insufficiently Random Values + CWE-307 Excessive Auth Attempts)
  • Reported privately by meifukun (https://github.com/meifukun)
  • Fixed at upcoming WeKan release
  • More details
-

SpliceBleed 2026-07-22 GitHub CodeQL (code scanning alert #425) and xet7
Process Automated code scanning flagged the incomplete multi-character sanitization.
Details
  • SpliceBleed — stripExploitPatterns() in imports/lib/fileNameDisplay.js removed HTML/script/XML/template markup from a shown filename in a single pass, so an input with nested or interleaved fragments (for example <scr<x>ipt> or <scr{{y}}ipt>) could have its inner part removed and the two surviving outer fragments spliced together into a fresh <script> token the single pass no longer re-examined (CWE-116 Improper Encoding or Escaping of Output)
  • GitHub CodeQL code scanning alert #425, rule js/incomplete-multi-character-sanitization, severity High
  • Fixed by applying the removals repeatedly until the string stops changing (a fixpoint loop); each pass only deletes text, so the string strictly shrinks and always terminates, and any dangerous token an earlier removal reveals is then removed too. Blaze {{ }} already HTML-escapes every rendered filename, so this is defence-in-depth on the displayed text rather than a live XSS, but the single-pass strip was genuinely incomplete
  • Fixed at upcoming WeKan release
  • More details
-

IdentityBleed 2026-07-22 GitHub CodeQL (code scanning alert #424) and xet7
Process Automated code scanning flagged the identity (no-op) replacement.
Details
  • IdentityBleed — a test in tests/securityLog.test.cjs built a menu-id regex with id.replace('report-', 'report-'), replacing a substring with itself: a no-op that CodeQL flags because it is almost always a mistake for a real transformation (CWE-116 Improper Encoding or Escaping of Output)
  • GitHub CodeQL code scanning alert #424, rule js/identity-replacement, severity Medium
  • Fixed by dropping the dead replace and matching 'js-' + id directly. Test-only code with no runtime exposure, but the no-op was removed for correctness
  • Fixed at upcoming WeKan release
  • More details
-

EscapeBleed 2026-07-17 GitHub CodeQL (code scanning alert #423) and xet7
Process Automated code scanning flagged the incomplete escaping.
Details
  • EscapeBleed — code that built a RegExp from a CSS declaration in tests/maximizedCardPosition.test.cjs escaped only parentheses (str.replace(/[()]/g, '\\$&')) instead of the full regex metacharacter set, so an input containing other metacharacters (including a backslash) would not be escaped correctly and the generated pattern could match the wrong thing (CWE-116 Improper Encoding or Escaping of Output)
  • GitHub CodeQL code scanning alert #423, rule js/incomplete-sanitization, severity High
  • Fixed by escaping the complete metacharacter set (str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')), matching the correct pattern already used elsewhere in the tests. Test-only code with a fixed, trusted input list — no injection exposure — but the incomplete escape was genuinely wrong
  • Fixed at upcoming WeKan release
  • More details
-

RandomBleed 2026-07-17 GitHub CodeQL (code scanning alert #422) and xet7
Process Automated code scanning flagged the biased randomness.
Details
  • RandomBleed — the startup schema upgrade (server/lib/schemaUpgradeSteps.js) generates Meteor-style document ids with crypto.randomBytes(len) mapped through byte % ID_CHARS.length. Because 256 is not a multiple of the 55-character alphabet, that modulo skews generated ids toward the first 36 characters (each ~1.4% more likely than the rest), reducing the entropy of the ids used for the swimlanes/lists/checklist-items the upgrade creates (CWE-1204 weak randomness)
  • GitHub CodeQL code scanning alert #422, rule js/biased-cryptographic-random, severity High
  • Fixed with rejection sampling: bytes at or above the largest multiple of the alphabet size (220) are discarded and resampled, so every character is exactly equally likely; ids stay Meteor-style 17 characters. A negative regression test pins that out-of-range bytes are never wrapped
  • Fixed at upcoming WeKan release
  • More details
CVE-2026-68899 GHSA-jhph-whx8-wq6p

MimeBleed 2026-07-14 HNUfwj (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • MimeBleed — file-upload MIME-type validation bypass leading to stored XSS (CVE-2026-68899 GHSA-jhph-whx8-wq6p, CWE-434). WeKan's upload validation (models/fileValidation.js) detects a file's real MIME type by running the Unix file command. On minimal Docker/Alpine images where file is not installed, detectMimeFromFile() silently returned undefined and the code fell back to the CLIENT-supplied fileObj.type. An authenticated board member (with WITH_API=true) could upload an HTML file containing JavaScript while setting fileType: "image/png": the spoofed type is not on the dangerous-MIME deny-list, so the dangerous-content scan was skipped and the file was stored, giving stored XSS served under the WeKan origin (session theft, actions as the victim, including admin)
  • CVSS:3.1 8.3 High (AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N)
  • Fixed so the client-supplied type can never gate the safety scan: when content-based detection via file is unavailable, WeKan falls back to a dependency-free JS content sniff (looksLikeDangerousMarkup()) that inspects the real bytes for HTML/SVG/XML/<script> signatures and forces the dangerous-content scan regardless of the claimed MIME, so a spoofed image/png that is really HTML+JS is rejected. The sniff only matches definitive markup, so genuine binary uploads (real PNG/JPEG/PDF, including large ones) are unaffected. WeKan also logs a one-time warning when file is missing (previously silent)
  • Affected container deployments without the file binary and WITH_API=true; fixed at the upcoming WeKan release
  • More details
CVE-2026-68561 GHSA-xm8x-c8wg-jhmf

SortBleed 2026-07-13 5ud0 / Tarmo Technologies (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • SortBleed — broken access control / privilege escalation: a low-privilege (comment-only / read-only) board member could escalate to board admin and take over a private board via the board sort collection-allow rule (CVE-2026-68561 GHSA-xm8x-c8wg-jhmf, CWE-863, CWE-269). To support drag-to-reorder, a second Boards.allow({ update }) rule returned true for any board member whenever the update touched the sort field. Meteor evaluates allow rules with OR semantics and does not scope an approving rule to the field that satisfied it: once any allow callback approves and no deny rejects, the ENTIRE modifier is applied. Because canUpdateBoardSort only checked that sort was AMONG the modified fields (not the only one), a comment-only / read-only member could smuggle arbitrary board mutations into the same $set as sort in one DDP Boards.update call — {$set: {sort: 99, members: [...self as admin...], permission: 'public', title: '...'}} — making themselves admin, flipping the private board to public, renaming it, and evicting the legitimate owner. The last-admin deny rule did not help because it only inspected $pull. Same allow-rule field-conflation class as BoardBleed (CVE-2026-55234), but on the Board document itself
  • CVSS:3.1 8.8 High (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
  • Fixed by restricting canUpdateBoardSort (server/lib/utils.js) so the sort-reorder rule approves an update ONLY when sort is the sole modified field (fieldNames is exactly ['sort']). Defense in depth: the last-admin deny rule (server/permissions/boards.js) now also rejects a $set rewrite of the members array that would drop the last active admin. The legitimate All Boards drag-reorder is unaffected — it persists order per-user in profile.boardSortIndex, not in the board document
  • Affected Wekan v9.85 and earlier through the current release; fixed at the upcoming WeKan release
  • More details
CVE-2026-68560 GHSA-x3xm-pxrv-jg7p

ScannerBleed 2026-07-05 DavidCarliez (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • ScannerBleed — shell injection (RCE) via a malicious upload filename in the external antivirus scanner command path. In models/fileValidation.js, when an admin-configured external scanner command line with a {file} placeholder is set, the uploaded file path was interpolated and run through asyncExec (promisify(exec)), which spawns /bin/sh -c and interprets all shell metacharacters. Wrapping the path in double quotes is not a shell boundary — inside double quotes the shell still expands $(...), backticks and \ — so a filename like $(touch /tmp/pwn).png or a`id`.png executed as the Wekan server process. Any authenticated user who can upload an attachment could trigger it. Same RCE class as AvatarBleed (CVE-2026-52891), but in a code path that was never covered by that fix (CVE-2026-68560 GHSA-x3xm-pxrv-jg7p, CWE-78)
  • CVSS:3.1 9.9 Critical (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H)
  • Unlike the sibling MIME-detection path (detectMimeFromFile, which already uses execFile with no shell) and unlike the AvatarBleed fix (which strips non-alphanumeric characters), this scanner path had zero sanitization. Fixed by POSIX single-quote-escaping the interpolated file path via a new shellQuote() helper — inside single quotes the shell interprets no metacharacters, so a malicious filename can no longer inject commands, while the admin's command line and the exact on-disk path are preserved
  • Affected Wekan v9.06 and earlier through the current release; fixed at the upcoming WeKan release
  • More details
CVE-2026-68559 GHSA-mwq8-ccpm-r533

ExcelBleed 2026-07-05 sec-reex (coordinated disclosure) and xet7
Process Did send detailed report with runtime-confirmed PoC!
Details
  • ExcelBleed — broken access control in the Excel-export route (GET /api/boards/:boardId/exportExcel): models/exportExcel.js called its guard exporterExcel.canExport(user) without await. Because canExport is async it returns an always-truthy Promise, so if (exporterExcel.canExport(user) || impersonateDone) was always true and the export ran regardless of the guard's real result. Any authenticated user could download the full contents of any private board they are not a member of (card titles + descriptions, lists, swimlanes, members, metadata). Same un-awaited async-auth bug class as BFLABleed, CloneBleed and TokenBleed (CVE-2026-68559 GHSA-mwq8-ccpm-r533, CWE-862, CWE-639)
  • CVSS:3.1 Moderate (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)
  • The Excel-export route was the lone remaining un-awaited canExport call site; the JSON export route (/export) was correctly awaited and returned 403 to the same non-member. Fixed by adding await, matching every other export route (export.js, exportPDF.js, exportExcelCard.js, import.js)
  • Affected Wekan v9.57.0 and earlier; fixed at the upcoming WeKan release
  • More details
CVE-2026-68558 GHSA-66m2-4wfr-c45p

DnsBleed 2026-07-01 4n207 (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • DnsBleed — the synchronous outgoing-webhook (board Integrations) URL validator in models/integrations.js blocks private/loopback/link-local IPs by regex-matching the URL hostname string and never resolves DNS, so a public hostname that resolves to a blocked address (e.g. 169-254-169-254.nip.io169.254.169.254, or any attacker A/AAAA record → internal IP) passes the blocklist. Incomplete-fix follow-up to WebhookBleed / IntegrationBleed RebindBleed (CVE-2026-68558 GHSA-66m2-4wfr-c45p, CWE-918)
  • CVSS:3.1 High (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N)
  • The reported PoC was already blocked at delivery by the RebindBleed fetchSafe guard and at REST input by validateAttachmentUrl(); this release completes the fix by making fetchSafe resolve both address families and validate through the single shared isIpBlocked block-list, removing the block-list drift the advisory points at
  • Affected Wekan v8.36 and later; fixed at the upcoming WeKan release
  • More details
CVE-2026-59154 GHSA-gv8h-5p3p-6hx7

ChecklistBleed 2026-06-20 DavidCarliez (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • ChecklistBleed — the Checklists/ChecklistItems DDP collection allow rules (server/permissions/checklists.js, checklistItems.js) authorized an update against only the document's CURRENT (source) cardId, never the destination. A low-privileged user could move a checklist/item they own onto a card in a private board they are not a member of by $set-ting a new cardId/checklistId (boardId is then denormalized from the destination card), writing attacker-controlled checklist data into the victim's private board — same class as BoardBleed, but for the card-attached checklist documents (CVE-2026-59154 GHSA-gv8h-5p3p-6hx7, CWE-863)
  • CVSS:3.1 Moderate (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N)
  • Fixed by adding denyCrossBoardMoveByCard/denyCrossBoardMoveByChecklistItem in server/lib/utils.js and a Checklists.deny/ChecklistItems.deny update rule that rejects any move whose destination board the caller cannot write to
  • Affected Wekan v9.62 and earlier; fixed at the upcoming WeKan release
  • More details
-

InputBleed 2026-06-18 GitHub CodeQL (code scanning alert #421) and xet7
Process Automated code scanning flagged the incomplete sanitization.
Details
  • InputBleed — stripHtml() in client/lib/importDependencies.js stripped HTML tags with a single pass of /<[^>]*>/g. That is incomplete: a dangling unclosed tag with no closing > (e.g. a trailing <script or <svg/onload=...) is never matched by the regex and survives untouched, leaving <script in the output; and removing one match can splice surrounding text into a new match. A crafted card-dependency ("Red Strings") import file could thus smuggle an HTML/script fragment past the sanitizer (CWE-79, CWE-80, CWE-116)
  • GitHub CodeQL code scanning alert #421, rule js/incomplete-multi-character-sanitization, severity High
  • Fixed by looping the tag-stripping replacement to a fixed point and then removing any remaining stray </> characters, so neither a complete nor a partial tag can remain
  • Fixed at Wekan v9.52 2026-06-18
  • More details
GHSA-jggc-qvfc-jr6x CVE requested

ProxyBleed 2026-06-15 rz1027 (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • 1. ProxyBleed — header-login IP allowlist bypass via X-Forwarded-For spoofing (GHSA-jggc-qvfc-jr6x, CWE-290, CWE-287, CWE-348). Wekan's header-login (reverse-proxy SSO) feature gated passwordless login on a source-IP allowlist (HEADER_LOGIN_TRUSTED_IPS) but read the client-supplied X-Forwarded-For header as the source IP. An unauthenticated attacker who can reach the app port directly sends a single GET request with a spoofed X-Forwarded-For: <allowlisted-ip> plus the username header (e.g. X-Auth-User: admin) and is minted a full passwordless login session (meteor_login_token) for any existing user including admin — complete account takeover and admin impersonation. An empty allowlist also failed open
  • CVSS: 9.8 Critical (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
  • The fix derives the source IP from the real TCP socket peer, only honors X-Forwarded-For when the immediate peer is a configured trusted proxy (taking the right-most untrusted hop), and fails closed when the allowlist is unset
  • Affected Wekan v9.44 and earlier
  • Fixed at See CHANGELOG (v9.46)
  • More details
CVE-2026-55234 GHSA-gm7v-pc38-53jr

BoardBleed 2026-06-11 0xzap (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • 1. BoardBleed — broken access control: any authenticated user could move their Cards/Lists/Swimlanes into a private board they are not a member of (cross-board write via collection allow rule) (CVE-2026-55234 GHSA-gm7v-pc38-53jr, CWE-284, CWE-639). The DDP write policies for Cards, Lists and Swimlanes authorized an update by checking only the document's CURRENT (source) boardId and never validated the NEW boardId in the update modifier; any logged-in user could $set boardId to a victim's private board over /cards/update, /lists/update or /swimlanes/update and inject attacker-controlled cards/lists/swimlanes into a board they cannot even read
  • CVSS: 7.x High (AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:L)
  • The REST move endpoint (PUT /api/boards/:boardId/lists/:listId/cards/:cardId with newBoardId) was not affected; it checks checkBoardWriteAccess on the destination board. Only the DDP allow/deny layer was vulnerable
  • Affected Wekan v9.35 and earlier
  • Fixed at See CHANGELOG (v9.37)
  • More details
CVE requested

TokenBleed 2026-06-10 Zion Boggan (coordinated disclosure) and xet7
Process Did send detailed report with PoC!
Details
  • 1. TokenBleed — unauthenticated login-token minting via un-awaited auth check in POST /api/createtoken/:userId (CWE-863, CWE-287). Authentication.checkUserId is async, so its 401/403 throws became rejected promises that a synchronous try/catch could not catch; the un-awaited call never stopped execution, so the handler minted and returned a usable login token for any user ID — including an admin — with no credentials (unauthenticated account takeover)
  • 2. The same detached-rejection bypass affected the other un-awaited checkUserId/checkAdminOrCondition handlers: GET /api/users, GET /api/users/:userId, PUT /api/users/:userId, POST /api/users/, DELETE /api/users/:userId, POST /api/deletetoken, GET /api/boards, GET /api/boards_count, DELETE /api/boards/:boardId, GET /api/users/:userId/boards and POST /api/boards/:boardId/copy (user enumeration, deletion, takeOwnership, board member changes and board deletion)
  • Affected Wekan v9.35 and earlier
  • Fixed at See CHANGELOG (v9.36)
  • More details
CVE-2026-53447 GHSA-qfqv-42qw-vvwh

CloneBleed 2026-06-04 dizconnectz (cloneBoard) and xet7 (similar issues found by code review)
Process Did send detailed report with full PoC!
Details
  • 1. CloneBleed — cloneBoard Meteor method had no authorization check: any user could clone (read) any private board by ID (CWE-639, CWE-862)
  • CVSS: 6.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)
  • 2. moveChecklist membership guard never ran (async helper unimported and un-awaited)
  • 3. updateListSort guard referenced an unimported function, so it never ran
  • 4. Attachment API methods/handlers called non-existent isBoardMember; card/board relationship not verified
  • 5. applyListWidth stored per-board list width with no board membership check
  • 6. getBackgroundImageURL returned any board's background by ID
  • 7. Missing-lists migration status/execute methods missing board authorization
  • 8. Attachment migration methods missing board authorization
  • 9. Outgoing webhook delivery trusted caller-supplied integration object
  • 10. userPositionHistory checkpoint methods missing board visibility check (PositionHistoryBleed class)
  • 11. Custom Field allow rules used membership not write-access — read-only members could write Custom Fields via DDP (ReadOnlyBleed class)
  • 12. Comment-reaction allow rules let read-only members add/remove reactions
  • 13. archiveBoard required only membership, not board admin (UI gates it behind admin)
  • 14. sendSMTPTestEmail required only login, not global admin
  • Affected Wekan v9.34 and earlier
  • Fixed at See CHANGELOG (v9.35)
  • More details
CVE-2026-53444 GHSA-cv95-8h7c-2ffq, CVE-2026-52893 GHSA-mp7g-hj5q-gxhq

OIDCBleed 2026-05-31 alexwaira (coordinated disclosure) and xet7
Process Did send detailed report!
Details
  • 1. Missing authorization on OIDC Meteor methods allows privilege escalation to admin (CVE-2026-53444 GHSA-cv95-8h7c-2ffq, CWE-269, CWE-862). Six OIDC-flow methods were globally DDP-callable; groupRoutineOnLogin could set isAdmin from caller data
  • 2. OIDC account takeover via unconditional email-based account merge in Accounts.onCreateUser (CVE-2026-52893 GHSA-mp7g-hj5q-gxhq, CWE-287)
  • Affected Wekan v9.31 and earlier
  • Fixed at Wekan v9.32 2026-05-31
  • More details
CVE-2026-52892 GHSA-6733-4wgq-8xvr

ReadOnlyBleed 2026-05-31 Wernerina (coordinated disclosure) and xet7
Process Did send detailed report!
Details
  • 1. Read-only board members could create/modify/delete Custom Fields (CVE-2026-52892 GHSA-6733-4wgq-8xvr, CWE-862). The six mutating Custom Field REST handlers used the read-level checkBoardAccess instead of checkBoardWriteAccess
  • Affected Wekan v9.31 and earlier
  • Fixed at Wekan v9.32 2026-05-31
  • More details
CVE-2026-53446 GHSA-hc3x-hq3m-663q, CVE-2026-53445 GHSA-7w2h-g83c-jqrp

WebhookBleed 2026-05-31 xet7
Process Found and fixed by code review.
Details
  • 1. Server-Side Request Forgery (SSRF) via webhook integration URLs — input-side validation (CVE-2026-53446 GHSA-hc3x-hq3m-663q, CWE-918). Builds on the v8.35/v8.36 IntegrationBleed delivery-layer fix
  • 2. Authorization bypass in copyBoard DDP method allows any user to copy private boards (CVE-2026-53445 GHSA-7w2h-g83c-jqrp, CWE-862). Tightened to require board admin, matching the REST endpoint
  • 3. Regression from the avatar RCE fix (CVE-2026-52891 GHSA-35j7-h385-2q9g): external antivirus scanner broken (asyncExec undefined)
  • Affected Wekan v9.31 and earlier
  • Fixed at Wekan v9.32 2026-05-31
  • More details
CVE-2026-52890 GHSA-g6vm-7757-pr88

FileBleed 2026-05-27 Jan Kahmen of turingpoint GmbH
Process Reported responsibly, fixed quickly.
Details
  • 1. Arbitrary file read and server DoS via attachment versions.original.path (CVE-2026-52890 GHSA-g6vm-7757-pr88, CWE-22, CWE-400)
  • Affected Wekan v9.30 and earlier
  • Fixed at Wekan v9.31 2026-05-27
  • More details
-

BFLABleed 2026-05-19 Fredrik Dietrichson
Process Did send detailed report with full PoC and runtime verification!
Details
  • 1. BFLABleed — Broken Function Level Authorization: 48 REST endpoints missing await on board access checks, allowing authenticated non-members to read/write any board.
  • CVSS: 8.1 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N)
  • Affected Wekan v9.20-v9.22
  • Fixed at See CHANGELOG
  • More details
-

AuthBleed 2026-05-07 11:39 EET Qiulin Deng
Process Did send detailed report with full PoC and runtime verification!
Details
  • 1. OIDCBleed
  • 2. CopyCardBleed
  • 3. CopyBoardBleed
  • 4. CopyListBleed
  • 5. DueDateBleed
  • 6. CopySwimlaneBleed
  • 7. MoveListBleed
  • CVSS: 9.1 — Affected Wekan v9.08 and earlier
  • Fixed at Wekan v9.09 2026-05-07
  • More details
-

AvatarBleed 2026-05-03 13:57 EET Trung Nguyen from CyStack Security
Process Did send detailed report and suggested fix!
Details
IntegrationBleed FileBleed CVE-2026-41455, IntegrationBleed RebindBleed CVE-2026-41454

IntegrationBleed 2026-02-24 15:09 EET Rodolphe GHIO
Process Did send detailed report and fix!
Details
-

AnchorBleed 2026-02-12 11:16 EET The GitHub Security Lab team
Process Did send detailed report and fix!
Details
  • 1. GHSL-2026-035_Wekan CursorBleed
  • 2. GHSL-2026-036_Wekan WatchBleed
  • 3. GHSL-2026-037_Wekan GlobalBleed
  • 4. GHSL-2026-044_Wekan CustomFieldBleed
  • 5. GHSL-2026-045_Wekan ImportBleed
  • Affected Wekan v8.33 and earlier
  • Fixed at Wekan v8.34 2026-02-20
  • More details
-

FloppyBleed 2026-01-24 18:30 EET Luke Hebenstreit of Twitter lheben_
Process Did send detailed report!
Details
-

SnowBleed 2026-01-05 15:46 EET Joshua Rogers of Aisle Research
Process Did send detailed report!
Details
  • 1. MigrationsBleed
  • 2. OrgsTeamsBleed
  • 3. ChecklistRESTBleed
  • 4. MigrationsBleed2
  • 5. PositionHistoryBleed
  • 6. SyncLDAPBleed
  • 7. AttachmentMigrationBleed
  • 8. MoveStorageBleed
  • 9. ListWIPBleed
  • 10. BoardTitleRESTBleed
  • 11. CardPubSubBleed
  • 12. FixDuplicateBleed
  • 13. LinkedBoardActivitiesBleed
  • 14. RulesBleed
  • Affected Wekan v8.19
  • Fixed at Wekan v8.20 2026-01-16 and Wekan v8.21 2026-01-18
  • More details
-

MegaBleed 2025-12-26 18:39 EET Joshua Rogers of Aisle Research
Process Did send detailed report!
Details
  • 1. IDOR in setCreateTranslation. Non-admin could change Custom Translation
  • 2. Private-only board setting can be bypassed
  • 3. Card comment author spoofing (IDOR) via API
  • 4. Cross-board card move without destination authorization
  • 5. Read-only roles can still update cards
  • 6. Checklist delete IDOR: checklist not verified against board/card
  • 7. Checklist create IDOR: cardId not verified against boardId
  • 8. Attachments publication leaks metadata without auth
  • 9. Attachment upload not scoped to card/board relationship
  • 10. LDAP filter injection in LDAP auth
  • Affected Wekan v8.18
  • Fixed at Wekan v8.19 2025-12-29
  • More details
-

SpaceBleed 2025-11-02 03:29 EET Siam Thanat Hack (STH)
Process Did send detailed report!
Details
  • 1. File Attachments enables stored XSS (High)
  • 2. Access to boards of any Orgs/Teams (High)
  • 3. Unauthenticated (or any) user can update board ‘sort’ (Low)
  • 4. Members can forge others’ votes (Low)
    Bonus: Similar fixes to planning poker too done by xet7.
  • 5. Attachment API uses bearer value as userId and DoS (Low)
  • Affected Wekan v8.15
  • Fixed at Wekan v8.16 2025-11-02
  • More details
CVE-2021-20654

JVN: Many fixed.

FieldBleed JVN: 2021-2025 Many fixed.
Cyb3rjunky and swsjona about input fields. Ryoya Koyama at Mitsui Bussan Secure Directions, Inc. (https://www.mbsd.jp/) about Javascript inside .SVG attachment
Romain Korpas at apitech.fr about IDOR. Nguyen Thanh Nguyen of Fortinet's FortiGuard Labs about SVG. Sho Sugiyama about XSS. And some anonymous security researchers.
Process Did send detailed report!
Details
  • XSS: Javascript saved to field, and Javascript inside .SVG attachment, is run when page is reloaded
  • Affected Wekan v3.12-v4.11
  • Fixed at Wekan v4.12 2020-06-08
  • More details
  • Fixed at WeKan v7.98 or earlier:
    • IDOR CWE-639 that affected WeKan 7.80-7.93: Romain Korpas at apitech.fr.
    • Computational Resource Abuse in Export endpoints: Anynymous Security Researcher.
    • FG-VD-22-078 Prevent SVG Billion Laughs Attack: Nguyen Thanh Nguyen of Fortinet's FortiGuard Labs.
    • usd-2022-0041 CWE-284 Improper Access Control: Christian Pöschl of usd AG.
    • JVN#14269684 Broken access control, JVN#74210258 Stored XSS, JVN#86586539 Stored XSS: Ryoua Koyama.
    • JVN#15385465 CWE-79 XSS: Sho Sugiyama.
    • JVN#80785288 CWE-79 XSS: Already previously fixed.
-

SocialBleed 2023-05-11 19.14 EET Rajesh Thapa
Process Did send detailed report!
Details
  • Security: Links to Social Media at wekan.fi could lead to theft of sensitive information
  • Affected Wekan website before 2024-05-12 05.34 EET
  • Fixed at Wekan website 2023-05-12 05.34 EET
  • More details
-

AdminBleed 2023-04-24 16.40 EET Christian Pöschl of usd AG Responsible Disclosure Team
Process Did send detailed report!
Details
  • Security: Non-Admin could change to Admin
  • Affected Wekan v6.85 and earlier
  • Fixed at Wekan v6.86 2023-04-26
  • More details
-

InvisibleBleed 2023-04-24 03.35 EET Someone at chat
Process Sent report and disappeared.
Details
  • Security: HTML comments not visible
  • Affected Wekan v6.85 and earlier
  • Fixed at Wekan v6.86 2023-04-26
  • More details
CVE-2023-31779

ReactionBleed 2023-02-28 12.36 EET Alexander Starikov at Jet Infosystems
Process Did send detailed report and fix!
Details
-

FileBleed 2023-02-16 17.35 EET SEC Consult, an Atos company
Process Did send detailed report!
Details
-

Emailbleed 2021-01-26 12.42 EET Georg Krause
Process Did send detailed report!
Details
  • Security: SMTP password visible to Admin at Admin Panel by using browser inspect to see behind asterisks
  • Affected Wekan v1.59-v4.98
  • Fixed at Wekan v4.99 2021-02-25
  • More details
CVE-2021-3309

LDAPBleed 2021-01-26 0:42 EET robert-scheck
Process Did send report and sent fix! Although, report was at public GitHub issue, not via Responsible Security Disclosure
Details
-

DUEBleed 2021-01-11 EET xet7
Process Did not notice security issue originally when merging new feature from pull request. Did fix issue when finally noticed it at production at Wekan demo server.
Details
  • Due Cards and Broken Cards: As Admin user, at All Users view of Due Cards and Broken Cards, fixed to not show cards from other users private boards. This affected only logged in Admin user, not logged in other users.
  • Affected Wekan v4.73-v4.74
  • Fixed at Wekan v4.75 2021-01-11
  • More details
VRF#20-08-SGSSC.

BypassBleed 2020-02-26 01:36 EET Dejan Zelic, Justin Benjamin and others at Offensive Security
Process Did send detailed report and helped fixing!
Details
  • Auth Bypass
  • Unauthenticated SSRF
  • DoS
  • Unauthenticated Username Change
  • Unauthenticated Os Statistics
  • Affected Wekan v0.7-v3.80
  • Fixed at Wekan v3.81 2020-03-01
  • More details
VRF#20-08-DDFJJ.

UserBleed 2018-06-12 Adrian Genaid at PLANTA Projektmanagement-Systeme GmbH
Process Did send detailed report and fix!
Details
CVE-2018-1000549,
In Progress Update Request 938446

BruteBleed 2018-06-12 Shadow Vault
Process Did not report to Wekan, was found later from CVE
Details
VRF#20-08-LZGVF.

FrameBleed 2018-03-25 Team
Process Did send detailed report!
Details
  • Cross Frame Scripting
  • Clickjacking
  • Improper Cache Control
  • Affected Wekan v0.7-v0.79
  • More details