Commit Graph
73 Commits
Author SHA1 Message Date
Lauri Ojansivu 6678c92e08 Security log: wire upload / metrics-XFF / export-authz remediation points.
Record more runtime rejections into the eventlog (Admin Panel Problems):
- fileValidation.js: log every upload rejection (dangerous MIME content ->
  xss.mime, mime not on the allow-list -> file.mime, over size limit ->
  file.size).
- metrics.js: log spoofing.xff when a /metrics request carrying an
  X-Forwarded-For header is denied (likely forged-whitelisted-IP attempt).
- export.js: log authz.export at all four export-authorization denial paths.
All calls are best-effort/guarded (server-only require, try/catch) so logging
never breaks the guard. Source-guard tests added.
2026-07-19 13:59:11 +03:00
Lauri Ojansivu 1669a1af19 Fix 7 security issues reported by meifukun.
- Avatar localization redirect SSRF: fetch avatars via fetchSafe (DNS-pinned,
  redirects rejected) instead of native redirect:follow, and validate
  profile.avatarUrl scheme (http/https/data:image/local) at write time.
- Trello import source.url stored XSS: only render/store an http(s) activity
  source URL, so a javascript: board url can no longer execute on click.
- Trello LIVE import readable SSRF: gate every attachment/background/avatar
  download with validateAttachmentUrl, matching the offline import path.
- CAS login global user-data race: store validated CAS user data per credential
  token instead of a module-global _userData (fixes account-takeover race).
- Metrics X-Forwarded-For whitelist bypass: only trust XFF behind
  METRICS_TRUST_PROXY (parsed spoof-resistantly from the right); else use the
  socket peer address.
- Stale impersonation export bypass: remove the "|| impersonateDone" export
  authorization bypass; require real board visibility (canExport) only.
- Invitation code brute force: generate invitation codes with a 128-bit CSPRNG
  (crypto.randomBytes) instead of a 6-digit Math.random value, and rate-limit
  createUser (DDPRateLimiter).

The OIDC shared serviceData race from the same report was already fixed (#4897,
the per-login objects are callout-local). Source-guard regression test added
(tests/securityMeifukun.test.cjs) and wired into test:unit:node.

Thanks to meifukun and xet7 !
2026-07-19 12:22:56 +03:00
Lauri Ojansivu 06fdede782 Admin Panel / Features / Security: import/export privacy controls
Six new optional toggles (all default off) governing how boards and user data
cross the WeKan boundary, enforced server-side so they cannot be bypassed from
the client:

- Disable all import / Disable all export: master switches that turn off every
  import/export feature. importBoard and cloneBoard call assertImportEnabled;
  every Exporter build()/buildStream() call assertExportEnabled. The import and
  export menu options are hidden in the UI via global importDisabled/exportDisabled
  Blaze helpers.
- Disable import avatars / Disable export avatars: never carry avatars into/out of
  WeKan. Import is gated at the single localizeAvatarFromBuffer choke point (covers
  WeKan JSON import, LDAP, OIDC/OAuth2 login sync and board-open localization) plus
  Trello inlineMemberAvatars; export skips the base64 avatar embed + avatarUrl in
  both Exporter paths.
- Anonymize import users / Anonymize export users: replace username/fullname/initials
  with counter placeholders (user1, user2, ...), drop avatars, and rewrite @username
  mentions + requestedBy/assignedBy in card/comment text. The placeholder word "user"
  is translated to the current user language. Export covers both build() and the
  streaming buildStream() (which does an id-only pre-scan so mentions streamed before
  the users array resolve to matching labels); import scrubs the incoming board in
  WekanCreator before any placeholder user or card is created.

New shared server helper models/lib/importExportSecurity.js holds the settings
read, guards, anonymization map builder and text rewriter. Adds settings
disableAllImport, disableAllExport, disableImportAvatars, disableExportAvatars,
anonymizeImportUsers, anonymizeExportUsers, published in the public setting.
2026-07-14 13:53:11 +03:00
xet7 41cd166358 Stream board exports (JSON, CSV/TSV, Excel) with bounded memory
The board export routes buffered the entire board in memory before sending:
JSON export built one object with every card, comment, activity, checklist and
base64 attachment; CSV called that same build(); Excel additionally loaded data
it never renders (activities/checklists/subtasks/rules) and did O(n^2)
result.cards.find() lookups. On big boards this peaked at gigabytes and could
exceed V8's max string length.

Now:
- Exporter.buildStream(res) writes the JSON document straight to the response a
  document at a time from raw Mongo cursors, encoding each attachment file to
  base64 in 3-byte-aligned chunks. Same _format/keys, so import round-trips.
- Exporter.buildCsvStream(res) keeps only the small lookup tables in memory and
  streams cards from a cursor, writing one CSV/TSV row at a time.
- ExporterExcel uses the exceljs streaming WorkbookWriter, committing each row
  to the response, drops the unused collections, and resolves parent/comment
  card titles via an id->title map instead of scanning all cards.
Peak memory stays flat regardless of board size.
2026-07-10 22:57:40 +03:00
Lauri OjansivuandClaude Opus 4.8 c1752c5fba Export big boards: optional JSON export without base64 attachments (#5870).
Big boards could not be exported as JSON because every attachment is base64-
encoded inline into one object that is then JSON.stringify-ed, which overflows
V8's maximum string length (and loads every attachment buffer into memory at
once). Adds an optional ?attachments=false query parameter to
GET /api/boards/:boardId/export that exports the board structure and attachment
metadata while skipping the base64 file data entirely, so large boards export
successfully. A matching "Export / JSON (without attachments)" entry is added to
the board export menu. The default export is unchanged (attachments still
included). Includes a REST regression test. Thanks to xet7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:35:28 +03:00
Lauri OjansivuandClaude Opus 4.8 309425545f Return proper status + body from board export error responses
The export endpoints passed a bare number to sendJsonResult (e.g. sendJsonResult(
res, 403)), but sendJsonResult treats its second arg as an options object, so a
number produced HTTP 200 with an empty body instead of the intended 4xx. Pass
{ code, data } so 404/400/403/auth failures return the correct status and a JSON
error body.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 15:53:36 +03:00
Lauri Ojansivu f0bce67a3b More Import Export and Rules features.
Thanks to xet7 and Claude !
2026-06-15 04:07:33 +03:00
Lauri Ojansivu 08ae61161c Fixed TokenBleed: unauthenticated login-token minting via un-awaited auth check in
`POST /api/createtoken/:userId`](https://github.com/wekan/wekan/blob/main/CHANGELOG.md)
(CWE-863, CWE-287). `Authentication.checkUserId` in `server/authentication.js` is an
`async` function, so its 401 (undefined `userId`) and 403 (not an admin) throws become
rejected promises rather than synchronous exceptions. The REST handlers in
`server/models/users.js` and `server/models/boards.js` called it without `await` inside a
plain synchronous `try/catch`, which cannot catch a rejected promise, so the failed check
never stopped execution. `POST /api/createtoken/:userId` then went on to mint and return a
usable login token for any user ID in the URL — including an admin — with no credentials at
all (unauthenticated account takeover). The same detached-rejection bypass also affected
`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`. Fixed by awaiting every async `Authentication` check (and
making the two non-`async` handlers `async`) so a failed check rejects before any privileged
code runs. The same un-awaited pattern in the board/card/Excel/PDF export handlers
(`models/export.js`, `models/exportExcel.js`, `models/exportExcelCard.js`, `models/exportPDF.js`,
which were backstopped by `exporter.canExport()`) and in the checklist-create handler
(`server/models/checklists.js`) was given the same await pass. Affected Wekan v9.35 and earlier.

Thanks to Zion Boggan, xet7 and Claude.
2026-06-10 19:39:05 +03:00
Lauri Ojansivu ce3e51b147 Fix Impersonate User. Show/Edit Avatar at Admin Panel/People/People.
Thanks to ahlgrimma, DnT1mmer, robbagithub, norrig and xet7 !

Fixes #6226,
fixes #6101,
fixes #3327,
fixes #4748
2026-04-07 09:52:41 +03:00
Harry Adel 63ce45c538 Split shared models from Meteor 3 server runtime 2026-03-24 01:50:39 +02:00
Harry Adel e8fee653c3 Meteor 3.4 migration: Phases 0-3
Phase 0 - Pre-migration cleanup:
- Remove msavin:usercache (unused), es5-shim, http@2.0.0, fibers
- Replace Meteor.wrapAsync in counters.js, exporter.js, attachmentUrlValidation.js
- Replace meteorhacks:subs-manager with Meteor.subscribe in 6 client files

Phase 1 - Create meteor-jade-loader:
- Custom Rspack/webpack loader for .jade templates
- Extracts mquandalle:jade-compiler pipeline (lexer, parser, transpiler)
- Bundles Meteor vendor packages (htmljs, html-tools, blaze-tools, spacebars-compiler)

Phase 2 - Package version bumps & replacements:
- Remove mquandalle:jade, dburles:collection-helpers, aldeed:simple-schema
- Remove communitypackages:picker (Meteor 3 bundles Express)
- Replace simple:json-routes -> communitypackages:json-routes
- Replace simple:rest-accounts-password -> communitypackages:rest-accounts-password
- Add collection-helpers shim at imports/collectionHelpers.js
- Convert Picker.route() to WebApp.handlers.get() in export files + sandstorm.js
- Add api.versionsFrom(['2.16', '3.0']) to all 9 custom packages
- Remove version pins from .meteor/packages

Phase 3 - Express 5 migration:
- Rename WebApp.connectHandlers -> WebApp.handlers (20 occurrences)
- Rename WebApp.rawConnectHandlers -> WebApp.rawHandlers (5 occurrences)
- Convert regexp route patterns to Express 5 named params in attachmentApi.js, avatarServer.js
2026-03-22 17:17:48 +02:00
Harry Adel 71eb01e233 Update ReactiveCache call sites to use async/await for Meteor 3.0
Part 3 of ReactiveCache async migration:
- Add await before all ReactiveCache.getX() calls
- Make functions containing ReactiveCache calls async
- Convert forEach/map/filter loops with async callbacks to for...of
- Update model helpers, Meteor methods, JsonRoutes handlers
- Update collection hooks (.before/.after insert/update/remove)
- Update .allow() callbacks to async

Files updated across models/ and server/ directories:
- Model files: cards, boards, lists, swimlanes, activities, users,
  checklists, checklistItems, customFields, attachments, integrations,
  cardComments, settings files, creators, exporters, and more
- Server files: publications, methods, notifications, routes, migrations
2026-02-01 00:54:38 +02:00
Lauri Ojansivu d0f118e7af Security Fix: Computational Resource Abuse in Export endpoints.
Thanks to Anynymous Security Researcher and xet7 !
2025-10-10 22:09:27 +03:00
Martin Filser 767d8e66e7 Move every ImpersonatedUsers.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 92052458f5 Move every Meteor.users.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 0767f50af8 Move every Users.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Jan Dvorak eb745106d8 Replace Picker for community packages version & small 2022-04-18 18:02:41 +03:00
Ben0it-T 11bf4c7c07 Fix : export CSV, TSV and XLS translation
Feature : add export CSV with semicolon separator
2021-10-03 09:18:02 +02:00
Lauri Ojansivu 3908cd5413 Fix: Impersonate user can now export Excel/CSV/TSV/JSON.
Impersonate user and export Excel/CSV/TSV/JSON is now logged into
database table impersonatedUsers.

Thanks to xet7 !

Fixes #3827,
fixes #3284
2021-05-29 00:19:12 +03:00
Vagner Nascimento 6eb90238b1 Included a new route to export (json) an attachment from a board.
GET  /api/boards/:id/attachments/:attachmentId/export
2021-03-26 22:37:42 -03:00
Lauri Ojansivu 1624fc82f7 Exports now work at #3173 at least for small boards. TODO: Fix EdgeHTML to work, before I can release this.
Thanks to xet7 !
2020-07-23 13:36:39 +03:00
Lauri Ojansivu afe00d02cd Add back checks about can user export CSV/TSV.
Thanks to marc1006 and xet7 !

Related #3173
2020-06-18 02:13:19 +03:00
Lauri Ojansivu 5eb3784527 Revert users changes that were made at Wekan v4.16.
Thanks to xet7 !
2020-06-18 02:00:51 +03:00
Lauri Ojansivu b00db983c8 Try to prevent errors on CSV/TSV export.
Thanks to xet7 !

Related #3173
2020-06-17 21:37:01 +03:00
Lauri Ojansivu f245b6b7fa Update users.js etc with global search replace, to try to fix selecting correct user.
Thanks to xet7 !
2020-06-17 20:21:44 +03:00
Bryan Mutai 8c149da9e9 Fix vote export to CSV/TSV & export currency custom field. 2020-05-27 01:23:31 +03:00
Lauri Ojansivu d52affe658 Move In Progress ostrio-files changes to separate branch, and revert ostrio-files changes, so that:
- Export to CSV/TSV with custom fields works
- Attachments are not exported to disk
- It is possible to build arm64/s390x versions again.

Thanks to xet7 !

Related #3110
2020-05-25 17:54:51 +03:00
Romulus Urakagi Tsai 921460db40 Fix export attachments (not tested) 2020-05-22 14:59:56 +08:00
Romulus Urakagi Tsai 4b196d5378 Merge branch 'master' of https://github.com/wekan/wekan into lib-change 2020-02-13 09:02:26 +00:00
izadpoor f868b3d1f9 fixed board export with attchment 2020-01-23 01:16:56 -05:00
Lauri Ojansivu 9b905c2833 Try to fix Node 12 Buffer() deprecation errors.
Thanks to xet7 !
2020-01-18 16:01:02 +02:00
Lauri Ojansivu e01f4dbf13 Change Buffer to Buffer.alloc on Node v12. Try to fix Snap. 2020-01-11 13:08:29 +02:00
Romulus Urakagi Tsai 4dcdec0084 Attachment upload from card done, need to fix download link 2019-11-20 10:40:09 +00:00
Lauri Ojansivu 00d581245c Fix typo on exporting subtasks.
Thanks to xiorcala !

Closes #2770
2019-10-29 22:02:30 +02:00
Lauri Ojansivu 7d6d3af54a Add Features: allowing lists to be sorted by modifiedAt when not in draggable mode.
Bug Fix #2093: the broken should be prior to file attachment feature introduced, and tested export board is working.

Thanks to whowillcare !

( xet7 merged this pull request manually from https://github.com/wekan/wekan/pull/2756 )

Closes #2093
2019-10-29 19:05:44 +02:00
Justin Reynolds 3eb4d2c341 Prettier & eslint project style update 2019-06-28 12:56:51 -05:00
Benjamin Tissoires 94c1367684 Restore export API
Commit 477d71e0b9 was based on an older version of export.js, which
means it reverted a few changes that were made previously.

Fixes #2328
2019-05-14 09:37:56 +02:00
Lauri Ojansivu 64ee60a008 Fix missing profile checks.
Thanks to justinr1234 !
2019-05-09 14:32:38 +03:00
Lauri Ojansivu ebfc8e5a1b Fix lint errors.
Thanks to xet7 !
2019-04-06 09:00:13 +03:00
Lauri Ojansivu 56cccc6781 Merge remote-tracking branch 'Angtrim/feature-duplicate' into edge 2019-04-06 08:46:40 +03:00
Angelo Gallarello 48216e1653 Minor fixes 2019-04-05 10:38:39 +02:00
Andrés Manelli 4cd0d1c397 Migrate customFields 2019-03-16 22:49:45 +01:00
Angelo Gallarello 477d71e0b9 Fixes 2019-02-12 23:40:12 +01:00
Lauri Ojansivu 32f896f19d - [Fix Sandstorm export board from web](https://github.com/wekan/wekan/issues/2157).
- [Fix Error when logging in to Wekan REST API when using Sandstorm Wekan](https://github.com/wekan/wekan/issues/1279).
  Sandstorm API works this way: Make API key, and from that key copy API URL and API KEY to below. It saves Wekan board to file.
  `curl http://Bearer:APIKEY@api-12345.local.sandstorm.io:6080/api/boards/sandstorm/export?authToken=#APIKEY > wekanboard.json`
  If later API key does not work, you need to remove it and make a new one.

Closes #2157,
closes #1279
2019-02-02 20:52:09 +02:00
Benjamin Tissoires 26d7ba72aa api: export board: allow authentication through generic authentication
This allows to retrieve the full export of the board from the API.
When the board is big, retrieving individual cards is heavy for both
the server and the number of requests.

Allowing the API to directly call on export and then treat the data
makes the whole process smoother.
2019-01-22 15:14:01 +01:00
Benjamin Tissoires ff467402c0 RESTAPI: Add some JSDoc
So we can have a decent REST API documentation generated.
2019-01-18 17:02:56 +01:00
Benjamin Tissoires 24f66c9f88 fix cards export
6eeb708e4d (Fix cards export and add customFields export.) is
incomplete as it allows to export newer cards inserted in the db after
the linkedId has been set, but not older cards present in an earlier
version of wekan.

Allow both null and empty value to be retrieved to match all cards.

related #1873
2018-10-23 18:02:15 +02:00
Lauri Ojansivu df84a2be9a Fix lint errors. 2018-09-16 01:50:36 +03:00
Lauri Ojansivu 6673b79738 Merge branch 'feature-rules' of https://github.com/Angtrim/wekan into Angtrim-feature-rules 2018-09-16 00:10:40 +03:00
Angelo Gallarello 8cb132f492 Export/Import done for rules 2018-09-14 19:20:24 +02:00