ae3b38958e
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [docker.io/wekanteam/wekan](https://redirect.github.com/wekan/wekan) | minor | `0e3461c` → `894f63f` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/18710) for more information. Add the preset `:preserveSemverRanges` to your config if you don't want to pin your dependencies. --- ### Release Notes <details> <summary>wekan/wekan (docker.io/wekanteam/wekan)</summary> ### [`v9.34`](https://redirect.github.com/wekan/wekan/blob/HEAD/CHANGELOG.md#v934-2026-05-31-WeKan--release) [Compare Source](https://redirect.github.com/wekan/wekan/compare/v9.33...v9.34) This release fixes the following bugs: - [Fix to not list all boards etc at Admin Panel / Attachments / Move Attachment](https://redirect.github.com/wekan/wekan/commit/fc10ce425910ce35fb6ea03a81b20ff870ac347e). Thanks to xet7. Thanks to above GitHub users for their contributions and translators for their translations. ### [`v9.33`](https://redirect.github.com/wekan/wekan/blob/HEAD/CHANGELOG.md#v933-2026-05-31-WeKan--release) [Compare Source](https://redirect.github.com/wekan/wekan/compare/v9.32...v9.33) This release adds [the following fixes](https://redirect.github.com/wekan/wekan/commit/6f021aa387d8c388821119b7f564565892ccc5ca), In Progress: Mobile / touch fixes (Fairphone 4 postmarketOS Firefox and Fairphone 4 Ubuntu Touch Morph browser; iPhone 12 Mini was already correct): - Fixed one-finger drag-to-scroll not working in the All Boards view and the Calendar view on Fairphone 4 Firefox and Ubuntu Touch Morph. These browsers do not emit the synthetic mouse events the `@wekanteam/dragscroll` library relies on, so scrolling only worked in the Swimlanes/Lists views. Added a new native touch-scrolling helper `client/lib/dragscrollTouch.js` that scrolls the nearest `.dragscroll` container with a one-finger drag (iOS is skipped, since native momentum scrolling already works there), and added the `dragscroll` class to the All Boards list and the Calendar view. - Fixed all text, buttons, the All Boards tables and the top bars (header and the second bar) rendering about 2x too large on Fairphone 4. `getMobileMode()` defaulted to mobile mode only for iPhone, so every other phone fell back to desktop mode, whose large desktop sizing looks oversized on a small phone screen. The default is now mobile mode for any phone-sized touch device (iPhone, Android/Mobile browsers, Ubuntu Touch, or a coarse-pointer touch screen with viewport width ≤ 800px); desktop browsers stay in desktop mode and the user's own Mobile/Desktop toggle still takes priority. - Fixed not being able to reorder swimlanes and lists by dragging their drag handle on touch devices. The new touch-scroll helper was hijacking touches that started on a drag handle; `.handle` / `.ui-sortable-handle` elements are now excluded from touch-scrolling so dragging the handle reorders as expected. - Fixed a card duplicating into two cards when it was dragged by its title-row drag handle while its Card Details panel was open. The card sortable in `client/components/lists/list.js` was re-initialized on every list re-render without first destroying the previous instance, so two `stop` handlers fired per drag. It now destroys any existing sortable before re-initializing, the same guard already used for swimlanes. Attachment storage: - Added configurable attachment storage backends in the admin panel: choose the default save storage and store attachments on the local filesystem, GridFS, or cloud object storage — S3-compatible (AWS S3, MinIO, Cloudflare R2, Backblaze B2, Wasabi, DigitalOcean Spaces), Azure Blob Storage, or Google Cloud Storage — via the `@tweedegolf/storage-abstraction` adapters (new `models/lib/cloudStorage.js`). Includes a "Test connection" action and English translations for the new settings. - Added a server-side bulk attachment move (new `server/attachmentBulkMove.js` and `models/attachmentBulkMoveStatus.js`) that moves all attachments from one storage backend to another as a background job whose progress survives the admin navigating away from or closing the page. Thanks to xet7. Thanks to above GitHub users for their contributions and translators for their translations. ### [`v9.32`](https://redirect.github.com/wekan/wekan/blob/HEAD/CHANGELOG.md#v932-2026-05-31-WeKan--release) [Compare Source](https://redirect.github.com/wekan/wekan/compare/v9.31...v9.32) This release fixes the following CRITICAL SECURITY ISSUES: - [Fix GHSA-hc3x-hq3m-663q: Server-Side Request Forgery (SSRF) via webhook integration URLs (CWE-918)](https://redirect.github.com/wekan/wekan/commit/0e5fef6f31164fd3de4db353d04173ee0490cd65). Wekan's outgoing-webhook integrations let a board admin store an arbitrary URL that is later fetched server-side, so a caller-controlled URL pointing at an internal address (cloud metadata at `http://169.254.169.254/latest/meta-data/`, loopback, RFC 1918 ranges, etc.) could be used to reach internal services or exfiltrate data. - **Originally fixed at the delivery layer in v8.35 and v8.36** (the [IntegrationBleed](https://wekan.fi/hall-of-fame/integrationbleed/) fixes). [Fix IntegrationBleed (v8.35)](https://redirect.github.com/wekan/wekan/commit/2cd702f48df2b8aef0e7381685f8e089986a18a4) routed webhook delivery in `server/notifications/outgoing.js` through `fetchSafe` (`server/lib/ssrfGuard.js`), which validates the URL and blocks private/loopback IPs, and [Fix RebindBleed of IntegrationBleed (v8.36)](https://redirect.github.com/wekan/wekan/commit/92beaa313706bc26fbea7e1cc8cfaf836609e038) hardened it further to resolve DNS once, pin the connection to the validated IP, and block redirects — closing the actual request-time SSRF including DNS rebinding. - **New in this release:** the missing input-side validation the advisory requested, added at the REST write paths in `server/models/integrations.js`. Those endpoints accepted webhook URLs without a robust check: `POST /api/boards/:boardId/integrations` relied only on the schema's regex `custom()` validator (no DNS resolution, blind to a hostname that resolves to a private IP and to decimal/octal/IPv4-mapped-IPv6 encodings), and `PUT /api/boards/:boardId/integrations/:intId` wrote the URL via `Integrations.direct.updateAsync`, which bypasses schema validation entirely, so updated URLs were never validated at the data layer. Both endpoints now run the DNS-aware `validateAttachmentUrl()` (`models/lib/attachmentUrlValidation.js`, the same validator already used for attachment imports) before storing the URL, rejecting private/loopback/link-local/reserved targets with HTTP 400. Together with the v8.35/v8.36 `fetchSafe` delivery guard and the schema validator on client-side inserts/updates, webhook URLs are now validated on every write path and again at delivery. Thanks to Claude. - [Fix GHSA-7w2h-g83c-jqrp: Authorization bypass in `copyBoard` DDP method allows any user to copy private boards (CWE-862)](https://redirect.github.com/wekan/wekan/commit/8940a103970c5da3f02b3615eef09fabfff421e3). The `copyBoard` Meteor method in `server/publications/boards.js` had no authorization check: any logged-in user could copy any board by ID — including private boards they are not a member of — cloning all cards, checklists, custom fields, labels and rules, while the equivalent REST endpoint `POST /api/boards/:boardId/copy` correctly required board admin. The method also looped over caller-supplied `properties` (`for (const key in properties) board[key] = properties[key]`) and copied them onto the new board, letting an attacker inject arbitrary fields such as `members` (to add themselves as admin of the copy) or `permission: 'public'` (to expose the copy to everyone). The member-level fix shipped in v9.09 as part of the AuthBleed fixes (caller must be authenticated, board must exist, caller must be a board member, and `members`/`permission` are stripped from `properties` before the copy). This release tightens it further to full parity with the REST endpoint: `copyBoard` now requires the caller to be a board admin (`board.hasAdmin(this.userId)`, the same `{isActive:true, isAdmin:true}` condition the REST API enforces via `checkAdminOrCondition`) rather than merely a member. - [Fix GHSA-cv95-8h7c-2ffq: Missing authorization on OIDC Meteor methods allows privilege escalation to admin (CWE-269, CWE-862)](https://redirect.github.com/wekan/wekan/commit/305864f0c77456ad0f2c1e616266c8a06749c951). Six Meteor methods used internally by the OIDC login flow were registered as globally DDP-callable with no authorization, while their non-OIDC counterparts require admin. `setCreateOrgFromOidc` and `setOrgAllFieldsFromOidc` (`server/models/org.js`), `setCreateTeamFromOidc` and `setTeamAllFieldsFromOidc` (`server/models/team.js`) let any authenticated user create/rename/ deactivate/modify arbitrary organizations and teams — including `orgAutoAddUsersWithDomainName` — bypassing the admin-only restriction. Most critically, `groupRoutineOnLogin` (`packages/wekan-oidc/oidc_server.js`) sets `isAdmin` from caller-supplied group data, so with `PROPAGATE_OIDC_DATA` enabled any authenticated user could call it over DDP with `{groups:[{isAdmin:true,forceCreate:true}]}` and promote themselves to global admin; `boardRoutineOnLogin` could likewise add the caller to the default board. These six methods are only ever invoked server-side (via `Meteor.callAsync`) during the OIDC handshake, where a fix that checks `isAdmin`/`this.userId` would break legitimate group/admin propagation (the user is not yet logged in or admin at that point). Fixed by rejecting any direct client/DDP invocation: a server-to-server `Meteor.callAsync` runs with `this.connection === null`, whereas a client call has a non-null connection, so each of the six methods now throws `not-authorized` when `this.connection !== null`. The legitimate OIDC login flow is unaffected. Thanks to alexwaira for the coordinated disclosure, and Claude. - [Fix GHSA-mp7g-hj5q-gxhq: OIDC Account Takeover via Unconditional Email-Based Account Merge in `Accounts.onCreateUser` hook (CWE-287)](https://redirect.github.com/wekan/wekan/commit/73204d4e0a7d77a1b186b3d76e8eaf2f3e7c9fd9). The `onCreateUser` hook in `server/models/users.js` unconditionally merged an incoming OIDC login into any existing Wekan account whose email **or** username matched the (attacker-controlled) OIDC claims — no ownership check, no email-verification check, no notification. An attacker who could present a matching `email`/`username` claim (trivial on self-hosted Keycloak/Authentik, where the `email`/`email_verified` claims are attacker-settable) inherited the victim's `_id`, boards, cards, attachments, API tokens and admin status, all during the attacker's own first OIDC login with no victim interaction. Fixed to fail closed, mirroring `LDAP_MERGE_EXISTING_USERS`: matching is now by email only (never username); auto-linking is opt-in via the new `OAUTH2_MERGE_EXISTING_USERS` setting (OFF by default, so the default deployment never merges); even when enabled the OIDC provider must assert `email_verified=true`; otherwise the OIDC login is rejected with `oidc-email-already-in-use` instead of merging. The provider's `email_verified` claim is now captured into the OIDC service data in `packages/wekan-oidc/oidc_server.js`. Thanks to alexwaira for the coordinated disclosure, and Claude. - [Fix GHSA-6733-4wgq-8xvr: Read-only board members could create/modify/delete Custom Fields](https://redirect.github.com/wekan/wekan/commit/70db04a93fedabe40331f21f86e6bdc91625914e). (privilege escalation via read-level authz on write operations, CWE-862). All six mutating REST handlers in `server/models/customFields.js` (POST/PUT custom-fields, POST/PUT/DELETE dropdown-items, DELETE custom-fields) called the read-level `Authentication.checkBoardAccess` instead of the write-level `checkBoardWriteAccess`, letting a board member with the read-only role (`isReadOnly` / `isReadAssignedOnly`) write Custom Field data via the REST API when `WITH_API=true`. Replaced the check with `checkBoardWriteAccess` in all six mutating handlers (the two GET handlers correctly stay on `checkBoardAccess`), mirroring `lists.js`/`swimlanes.js`/`cards.js`. Thanks to Wernerina for the coordinated disclosure, and Claude. - [Fix regression from the avatar RCE fix GHSA-35j7-h385-2q9g: external antivirus scanner broken (`asyncExec` undefined)](https://redirect.github.com/wekan/wekan/commit/8ea5a6a097f1b598688a94832e94bd1ec1b34cd6). The avatar RCE fix renamed `asyncExec` to `asyncExecFile` in `models/fileValidation.js`, but the admin-configured external scanner command line still called the now-undefined `asyncExec`, throwing `ReferenceError` (swallowed by the catch) and making every upload silently fail validation whenever an external scanner was configured. Restored a shell-based `asyncExec` used only for that admin-configured command line; MIME detection still uses the shell-free `asyncExecFile`. Thanks to Claude. - [Fix CodeQL 68: Polynomial regex DoS in Jade parser](https://redirect.github.com/wekan/wekan/commit/ae671bc70a0b2e0bb0cdcf24130477a0dd72ea72). Thanks to CodeQL and Claude. - [Fix CodeQL 69: Polynomial regex DoS in Jade parser, part 2](https://redirect.github.com/wekan/wekan/commit/105199991f2944ac431906e5b5cbeb10de003870). Remove the redundant `$` anchor from the interpolation regex in `compiler.js` and bundled `jade.js`. The greedy `[\s\S]*` already matches to end of string, so dropping `$` keeps the same match while eliminating the backtracking that CodeQL alert `js/polynomial-redos` flagged. Thanks to CodeQL and Claude. - [Fix CodeQL 63: Incomplete string escaping or encoding in bundled `jade.js`](https://redirect.github.com/wekan/wekan/commit/b4b81684e0d28406c6499b9ba6bf33b301a3faa9). In uglify-js's `make_string` (bundled twice into jade's browser bundle), the chosen quote was escaped in a trailing `str.replace(/'/g, "\\'")` that CodeQL alert `js/incomplete-sanitization` flags for not escaping backslashes in that same call. Backslashes were already escaped in the earlier single-pass `replace`, so this was a local false positive, but the fix folds the quote escaping into that same pass (escaping both quotes), making the escaping atomic and complete while keeping the emitted string literals decode-equivalent. Thanks to CodeQL and Claude. - [Fix CodeQL 67: Incomplete multi-character sanitization](https://redirect.github.com/wekan/wekan/commit/66d15f6ab0b3c42ae5de565490645d4c83f0a997). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 60: Useless regular-expression character escape](https://redirect.github.com/wekan/wekan/commit/fc76d0e5767f021cae3d466147e5f7695594ac8c). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 58: Incomplete multi-character sanitization](https://redirect.github.com/wekan/wekan/commit/13f78f620709f16e753a0831faa7f98cfcf5c58e). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 57: Incomplete multi-character sanitization](https://redirect.github.com/wekan/wekan/commit/36274f35f4de10a9f271cb8fc1154499fe8a2415). Thanks to CodeQL and GitHub Copilot. - Fix CodeQL 56: Incomplete string escaping or encoding]\([`c5e4260`](https://redirect.github.com/wekan/wekan/commit/c5e42607af5a0a396c0c85dba3652b8be28a2ff3)). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 55: Incomplete string escaping or encoding](https://redirect.github.com/wekan/wekan/commit/50728616871b0db8e05d5391ea479ae8099236d1). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 48: Clear-text logging of sensitive information](https://redirect.github.com/wekan/wekan/commit/b6564c81f1cbfc6bdf0b4bd72fc9a9ce36b36f6e). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 418: Clear-text logging of sensitive information](https://redirect.github.com/wekan/wekan/commit/f882a14ee07e6fbef16594851a773275d6547dba). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 419: Clear-text logging of sensitive information](https://redirect.github.com/wekan/wekan/commit/6b923eb4c21ef66c2d4ff859ffed4293365aaf9f). Thanks to CodeQL and GitHub Copilot. - [Delete calendar demos, so that CodeQL stops complaining](https://redirect.github.com/wekan/wekan/commit/d0b2b5201e8a43a067ca32b0cf6a542695213406). Thanks to xet7. - [Fix CodeQL 35: Insecure randomness](https://redirect.github.com/wekan/wekan/commit/358d893c3382ca90a408055713d9b6ffda73f33a). Thanks to CodeQL and GitHub Copilot. - [Fix CodeQL 417: Workflow does not contain permissions](https://redirect.github.com/wekan/wekan/commit/7836ce27e7d20a3db585c56a565423e4fcc00f0b). Thanks to CodeQL and GitHub Copilot. and adds the following updates: - [Added test menu options](https://redirect.github.com/wekan/wekan/commit/b0918686a2e3e39511964be14321f30b5520c644). "Test Playwright Chromium", "Test Playwright Firefox" and "Test Playwright Webkit" to `rebuild-wekan.sh` for running the Playwright end-to-end test suite per browser. Thanks to xet7. - [Copy wepica style of hide/show password to WeKan login and register pages](https://redirect.github.com/wekan/wekan/commit/9d3587086377c6c677ee03d4cb6f43c34f468558). Thanks to Chostakovitch and xet7. - Updated dependencies. [Part 1](https://redirect.github.com/wekan/wekan/commit/29b0cc1f86d0feb8d7c963ab9f4de2e8d86aac1b), [Part 2](https://redirect.github.com/wekan/wekan/commit/136931640186cd2969bb3e8690a2d9f01a6ef544), [Part 3](https://redirect.github.com/wekan/wekan/commit/76945ee5b51b2e57eef008e1fa9e30b56a5dbd92), [Part 4](https://redirect.github.com/wekan/wekan/commit/a2e76f2cf0b5f6fecf2d7305ddc97573425885b6), [Part 5](https://redirect.github.com/wekan/wekan/commit/08084d96e8a67055fd2433f5c0d25828f23be9b7), [Part 6: Fork and update meteor-node-stubs](https://redirect.github.com/wekan/wekan/commit/06c803388ba71e76194e5f201a296782d774fa07), [Part 7](https://redirect.github.com/wekan/wekan/commit/ac0e11e54831206ab8e36498384c2ef5ea62489e), [Part 8](https://redirect.github.com/wekan/wekan/commit/42d79b3dcf820b1a74d3930523557737a7389f37). Thanks to developers of dependencies. and adds the following new features: - [Add User board access roles to Admin Panel / People / Roles](https://redirect.github.com/wekan/wekan/commit/c956ab5a4e2d675641f8c74df2dcde675474ab06). A new global "Roles" tab in Admin Panel / People lets a site admin choose which board roles are allowed to invite users to a board ("Allow Invite to Board"). Each board role has its own toggle — Board Admin, Normal, Worker, Comment only, No comments, Only Assigned Normal, Only Assigned Comment, Read Only and Only Assigned Read — plus an "All Board Members" master toggle that selects them all. The policy is enforced server-side in the `inviteUserToBoard` and `searchUsers` methods, and the add-member button in the board sidebar is shown only to roles the policy allows. Global Admin Panel users (site admins) always have all rights and cannot be restricted here; this is kept clearly distinct in code from the per-board "Board Admin" role. Secure default: only Board Admin and Normal may invite. Thanks to xet7. and fixes the following bugs: - [Fix typos](https://redirect.github.com/wekan/wekan/commit/64b43a42ddc55f4196845834234035a9da0a6bd1). Thanks to xet7. - [Fix iOS Chrome jQuery event handler runtime error](https://redirect.github.com/wekan/wekan/commit/0fefdeec4cdca73c00524c49be80060b53dfa0e5). Thanks to xet7. Thanks to above GitHub users for their contributions and translators for their translations. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://redirect.github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMzAuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEzMC4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImFwcC93ZWthbiIsImF1dG9tZXJnZSIsInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvbWlub3IiXX0=-->