454 Commits
Author SHA1 Message Date
Ahmed Tawfik f6d7d90bde Initial commit: PLANKA project
Build and Test / build-and-test (push) Failing after 6m57s
Build and Push Docker Nightly Image / build-and-push-docker-nightly-image (push) Canceled after 0s
2026-09-22 02:20:23 -04:00
Daniel Hiller b581a97c2c feat: Show how many cards a list holds
A board level switch, off by default. With it on, each list puts its card
count on the add-card button. Useful to a board that is being kept to a size
and noise to one that is not, which is why it is a choice rather than always
on.

The count is every card in the list, not the ones a filter leaves visible.
Those answer different questions: how full is this list, versus how many match
what I am looking at right now. The first is the one a counter is for, and it
is also what the same switch counts in Pro, so a board keeps its meaning
across an upgrade.

The column matches Pro's name, type and default, so the setting survives that
upgrade rather than being dropped on the way.
2026-09-17 03:51:40 +02:00
Daniel Hiller 3edce1cc04 fix: Date the webhook scope migration after the one before it
The file came in named 20260502000000, which sorts ahead of the TOTP attempt
limit from August. Knex records migrations in the order it runs them, so the
last row in the table is not the same on every instance: a fresh install runs
both in name order and ends on the August one, while an instance that already
had it runs only this one and ends here.

Pro reads that last row to recognise which Community version it is upgrading
from, and it can only carry one name per version. Renaming to a timestamp
after the August migration makes the last row the same everywhere.

The rename is safe while this is only a few commits old on master and in no
tag. Anyone who pulled in that window and already ran it would see knex offer
it a second time.
2026-09-17 02:38:56 +02:00
Daniel Hiller 35f14b479c Merge pull request #1650 from symonbaikov/feature/webhook-scope-filter
feat: filter webhooks per project, board, and account
2026-09-17 02:00:30 +02:00
Daniel Hiller 7024673632 Merge pull request #1645 from symonbaikov/feature/apprise-config-options
feat: add operator config options for Apprise notifications (closes #1576)
2026-09-17 02:00:24 +02:00
Daniel Hiller 8236cde954 fix: Keep the seed from refusing to start an instance that already ran
The validation added with the admin user checks reached further than intended.
The seed runs on every container start, not only on the first, and it threw on
three conditions that are normal on a second start.

The worst was the check for an existing user: after the first start the
default admin exists by definition, so every restart after that ended in a
container that would not come up. The insert is wrapped in a try and falls
back to an update precisely because it is meant to run again, and that path
was never reached.

The other two were narrower but the same shape. `validator.isEmail` rejects
`admin@localhost`, which is a common value in self-hosted setups, so an
instance that had been running for a year would stop coming up after the
upgrade.

None of it throws now. Bad input is reported on stderr and skipped, the way
an invalid username already was, and a username that belongs to someone else
is left alone rather than taken. `db:create-admin-user` keeps the strict
validation, which is where a person is there to read it and type again.
2026-09-17 00:48:08 +02:00
Daniel Hiller 84827ab354 Merge pull request #1683 from symonbaikov/feat/negative-label-filter
Add negative label filtering for cards

Two conflicts, both from work that landed while this branch was open.

In the endless list query, master had added an ORDER BY so the cursor and the
limit agree. The exclusion clause belongs in the WHERE part, so it is placed
before it rather than after; the other way round the statement does not parse.

The label item had been restructured here for the tri-state filter and had
gained a tooltip on master. The restructured version is kept and the tooltip
put back on top of it, which also brings back the translation hook this branch
had dropped.
2026-09-17 00:46:31 +02:00
Daniel Hiller caa3f720e9 Merge pull request #1723 from AymanAlSuleihi/fix/create-admin-user-seed-validation
fix: Create admin user seed validation
2026-09-17 00:44:37 +02:00
Daniel Hiller f7aefd9af3 Merge pull request #1777 from plankanban/dependabot/npm_and_yarn/server/js-yaml-4.3.2
build(deps-dev): Bump js-yaml from 4.3.1 to 4.3.2 in /server
2026-09-17 00:40:12 +02:00
Daniel Hiller 14ea440ade Merge pull request #1776 from plankanban/dependabot/npm_and_yarn/server/sharp-0.35.4
build(deps): Bump sharp from 0.35.3 to 0.35.4 in /server
2026-09-17 00:40:06 +02:00
Daniel Hiller 7ad0f9b324 Merge pull request #1775 from plankanban/dependabot/npm_and_yarn/server/nodemailer-9.1.1
build(deps): Bump nodemailer from 9.0.3 to 9.1.1 in /server
2026-09-17 00:40:00 +02:00
dependabot[bot] 8ac152f00e build(deps-dev): Bump js-yaml from 4.3.1 to 4.3.2 in /server
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.1 to 4.3.2.
- [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.2/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.3.1...4.3.2)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-13 05:00:27 +00:00
dependabot[bot] 6425a2ac17 build(deps): Bump sharp from 0.35.3 to 0.35.4 in /server
Bumps [sharp](https://github.com/lovell/sharp) from 0.35.3 to 0.35.4.
- [Release notes](https://github.com/lovell/sharp/releases)
- [Commits](https://github.com/lovell/sharp/compare/v0.35.3...v0.35.4)

---
updated-dependencies:
- dependency-name: sharp
  dependency-version: 0.35.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-11 04:11:58 +00:00
dependabot[bot] 75608c33fd build(deps): Bump nodemailer from 9.0.3 to 9.1.1 in /server
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 9.0.3 to 9.1.1.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v9.0.3...v9.1.1)

---
updated-dependencies:
- dependency-name: nodemailer
  dependency-version: 9.1.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-10 02:48:58 +00:00
dependabot[bot] 296f869ce7 build(deps-dev): Bump fast-uri from 3.1.5 to 3.1.7 in /server
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.5 to 3.1.7.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.5...v3.1.7)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-02 23:42:14 +00:00
Daniel Hiller de4d768831 fix: close the gaps a security review found in the default install
Reported against 2.2.1 by someone reading the source. Every finding held.

**Sign-in had no ceiling.** Failures were logged with the caller's address
and nothing more. Two counters now — one per address, one per account —
because the two attacks look different: one source working through many
accounts is caught by the first, many sources working on one account by the
second, and behind a proxy only the second still means anything.

The count is kept in the process that serves the request. PLANKA needs no
Redis and the stock deployment is one container; run several and each keeps
its own count, which multiplies the ceiling by their number. That trade is
written where the limits are configured.

**The second factor could be guessed at leisure.** Six digits, and a
pending token that stayed valid for its full ten minutes however many codes
were wrong. Wrong codes are now counted on the session row — in the
database, so the count survives a restart and holds across every process —
and when the budget is spent the session is destroyed. After that even the
right code is refused and the login starts over from the password.

**Avatars, background images and favicons** checked the token's signature
and nothing else, so a revoked session, a deactivated account or a changed
password all kept working there for as long as the signature lasted, which
is a year by default. The five checks the API makes now live in one helper
that both use, rather than the shortened copy that had drifted from it.

**A link attachment's favicon** was fetched from wherever the URL pointed.
Storing a link is harmless — it is a string the user typed — but fetching
its icon is a request the server makes to an address the user chose, and
whether an icon came back reported on what is reachable from inside the
network. Server-side fetches now refuse private, loopback and link-local
addresses, `169.254.169.254` among them. The attachment is still created:
linking to an internal wiki is a legitimate thing to do, and it was the
server's own request that had to stop.

**The signing key.** Our own compose file ships `notsecretkey`, and it is
printed in the documentation — so on any instance that copied it, anyone can
sign a token for any account. PLANKA now says so on every start, and keeps
saying it, along with a key that is missing or shorter than 32 characters.
The placeholder carries the warning inline, where it is copied from.

**The backup script** wrote password hashes, live sessions, TOTP secrets and
SMTP credentials to an unencrypted archive. `BACKUP_PASSPHRASE` now encrypts
it, and without one the script says what it just put on disk. It also says
what it is — an example for the stock compose stack, not a backup concept —
and names the window between the database dump and the file copy, which no
ordering closes.
2026-08-28 20:55:54 +02:00
Daniel Hiller d7da44efe4 feat: Add script to clean orphaned reference records
Instances that accumulated project managers, favorites, board memberships
or board subscriptions pointing at a project or board that no longer exists
had no way to find or clear them.

The script reports by default and only deletes with `--apply`, which first
asks whether a backup exists and refuses outright without a terminal to ask
on. It removes nothing but reference rows: structural orphans such as a
board without a project carry user content, and a membership whose
denormalized project is stale still grants real access to an existing
board, so both are reported and left alone.
2026-08-26 09:31:18 +02:00
Daniel Hiller 2d289cd3d5 fix: Make endless list pagination deterministic
The filtered branch of `getByEndlessListId` applied `LIMIT` without an
`ORDER BY`, so Postgres was free to hand back any matching rows. With a
search over 64 cards the first page returned the oldest ones and a full
cursor walk reached 60 of them across 149 rows — cards both skipped and
repeated. The query now orders the way the cursor reads it.

The cursor itself is validated as ISO 8601, which admits forms Postgres
rejects as a timestamp (`2026`, `2026-W35-3`, a comma as the decimal
separator), each of them a 500 from the adapter. It is normalized before
the query, and stays a string because the equality half of the cursor
reads a `Date` as an empty constraint.
2026-08-26 09:23:01 +02:00
Daniel Hiller 4add7e43af fix: Keep dangling project references from blanking the home view
`getManagerProjectsModelArray` mapped every project manager to its project
without checking that the project is in the store, so one row pointing at a
deleted project produced a null the caller then read `id` off — taking down
the whole home view. `getMembershipProjectsModelArray` had the same hole one
level up, destructuring `board.project` before testing `board`.

The projects endpoint fed exactly that state: it derived the id list for the
included records from the manager rows, so a `project_manager` row whose
project no longer exists shipped a manager for a project missing from `items`.
Board memberships had the same gap. Both id lists now come from the records
that actually exist.
2026-08-26 09:22:53 +02:00
Daniel Hiller 266246e242 chore: Update version 2026-08-10 18:28:48 +02:00
Daniel Hiller bd487e3f9f fix: Prevent path traversal in local file manager
The local file manager joined attacker-controlled path segments into the
uploads storage path without ensuring the result stayed under the uploads
root. Any authenticated user could read arbitrary files readable by the
Planka process (e.g. /etc/passwd, /app/.env) via `../` sequences on the
/user-avatars/*, /background-images/* and /favicons/* routes (CWE-22).

Resolve the path and enforce it stays within uploadsBasePath, centrally in
buildPath so every local file operation is covered. Additionally resolve
symlinks in read() and re-check containment, so a symlink inside the root
cannot be used to escape it.

Reported by Alpesh (github.com/Alpastx).
2026-08-10 03:00:29 +02:00
Daniel Hiller 2684198bf8 chore: Update version 2026-08-09 22:36:27 +02:00
Daniel Hiller 3ef87a8603 feat: Add configurable auto logout on inactivity
Users can pick an inactivity timeout in their preferences. A warning
appears 30 seconds before, and activity or a logout is synchronised
across open tabs.
2026-08-08 00:24:16 +02:00
Daniel Hiller 2e4904f77d feat: Add two-factor authentication via TOTP
Adds TOTP setup with QR code, login challenge, recovery codes and
trusted devices that let a browser skip the second factor for 30
days. Admins can reset another user's second factor by confirming
with their own password.
2026-08-07 20:11:55 +02:00
Daniel Hiller 36aa732fec feat: Remove OIDC and SSO support
Existing SSO accounts have no local password, so the migration
deactivates them before dropping is_sso_user and the
identity_provider_user table.
2026-08-07 19:15:43 +02:00
Daniel Hiller a1f0a2b3fa chore: Update dependencies 2026-08-07 16:45:51 +02:00
Daniel Hiller bec5dd1597 chore: Update dependencies
Bump Node to 24 in Dockerfile and Dockerfile.dev.
Bump sharp to 0.35, nodemailer to 9 and concurrently to 10.
Add overrides for body-parser, qs, multiparty, uuid, diff,
serialize-javascript, linkify-it and svgo to pull in security fixes
that upstream pins block.
Rename the sails patch to match 1.5.18.
2026-08-07 16:17:24 +02:00
Ayman c587a1441d fix: Add password validation for admin user seeding process 2026-07-08 08:05:00 +01:00
Ayman aeb3456091 refactor: Replace while true with flag based validation 2026-07-08 07:42:04 +01:00
Ayman 2f5252faad fix: Add email uniqueness check to admin user seeding process 2026-07-08 07:17:39 +01:00
Ayman 7fbc2ea737 fix: Add username uniqueness check to admin user seeding 2026-07-08 07:17:32 +01:00
Ayman 0a2641db84 fix: Add email validation to admin user seeding process 2026-07-08 07:17:26 +01:00
Ayman 062cc3c347 fix: Add name length validation to admin user seeding process 2026-07-08 07:17:14 +01:00
Ayman 1d523cdab5 fix: Add username validation to admin user seeding process 2026-07-08 07:17:05 +01:00
Symon 55d0e2f877 Add negative label filtering for cards 2026-06-05 16:43:45 +03:00
dependabot[bot] 8940a1dfa6 build(deps): Bump ws, engine.io and socket.io-adapter in /server
Bumps [ws](https://github.com/websockets/ws), [engine.io](https://github.com/socketio/socket.io) and [socket.io-adapter](https://github.com/socketio/socket.io). These dependencies needed to be updated together.

Updates `ws` from 8.18.3 to 8.20.1
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.18.3...8.20.1)

Updates `engine.io` from 6.6.6 to 6.6.8
- [Release notes](https://github.com/socketio/socket.io/releases)
- [Changelog](https://github.com/socketio/socket.io/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io/compare/engine.io@6.6.6...engine.io@6.6.8)

Updates `socket.io-adapter` from 2.5.6 to 2.5.7
- [Release notes](https://github.com/socketio/socket.io/releases)
- [Changelog](https://github.com/socketio/socket.io/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io/compare/socket.io-adapter@2.5.6...socket.io-adapter@2.5.7)

---
updated-dependencies:
- dependency-name: ws
  dependency-version: 8.20.1
  dependency-type: indirect
- dependency-name: engine.io
  dependency-version: 6.6.8
  dependency-type: indirect
- dependency-name: socket.io-adapter
  dependency-version: 2.5.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-29 11:28:05 +00:00
Symon 05979a460f feat: filter webhooks per project, board, and account
Adds optional project, board, and acting-user scope to each webhook so
events from a specific board or project can be routed to a single
endpoint without an external automation tool in the middle (closes
#1457).

A webhook now fires for an event only when every set scope matches:
empty scope still means "fire for everything", keeping existing
webhooks working unchanged. Scope filtering is centralized in the
sendWebhooks helper, which auto-derives projectId/boardId from the
event payload, so existing call sites are untouched.
2026-05-02 10:31:30 +03:00
Symon 52edbcc2f8 feat: add operator config options for Apprise notifications (closes #1576)
Adds three new environment variables that give instance operators control
over Apprise notification services, addressing GDPR and compliance concerns
around third-party data transfers.

## New environment variables

- APPRISE_ENABLED (default: true)
  Set to "false" to globally prevent users from creating Apprise notification
  services and to silently skip sending any Apprise notifications. Existing
  services in the database are preserved but not used while disabled.

- APPRISE_ALLOWED_SCHEMAS (default: empty — no restriction)
  Comma-separated allowlist of Apprise URL schemas (e.g. "slack,tgram").
  When set, only services whose URL schema appears in this list can be
  created or will be sent. Takes priority over APPRISE_BLOCKED_SCHEMAS.
  Uses Apprise's internal schema names (e.g. "tgram" for Telegram).

- APPRISE_BLOCKED_SCHEMAS (default: empty — built-in list applies)
  Comma-separated blocklist of Apprise URL schemas (e.g. "discord,slack").
  When set, replaces the built-in blocked list entirely. When empty, the
  built-in list (syslog, dbus, kde, qt, glib, gnome, macosx, windows)
  continues to apply as a fallback.

## Enforcement

Validation happens at two layers:

1. API layer (create endpoints for user and board notification services)
   Returns HTTP 403 when Apprise is disabled, HTTP 422 when the URL schema
   is not permitted. This gives users immediate feedback in the UI.

2. Python send layer (send_notifications.py)
   The schema config is passed as a JSON argument so the same allow/block
   rules apply at send time, guarding against services that were created
   before the config was tightened.

## Files changed

- server/config/custom.js — parse new env vars via existing envToArray helper
- server/utils/send_notifications.py — accept schemaConfig as argv[4]; replace
  hard-coded BLOCKED_SCHEMAS_SET with dynamic allowed/blocked resolution
- server/api/helpers/utils/send-notifications.js — short-circuit when disabled;
  pass schemaConfig JSON to the Python script
- server/api/helpers/notification-services/create-one-in-{user,board}.js — add
  appriseDisabled and schemaNotAllowed exits with schema validation logic
- server/api/controllers/notification-services/create-in-{user,board}.js — wire
  new exits to forbidden (403) and unprocessableEntity (422) responses
- server/.env.sample — document all three new variables with comments
2026-04-26 23:44:52 +03:00
Daniel Hiller e429b478ca chore: Bump version to 2.1.1 and update release notes 2026-04-18 15:10:14 +00:00
Daniel Hiller 0e5dedd627 Merge pull request #1638 from plankanban/dependabot/npm_and_yarn/server/multi-e6e4b50ff7
build(deps): Bump underscore and @sailshq/nedb in /server
2026-04-18 16:23:01 +02:00
dependabot[bot] a9f28b45f4 build(deps): Bump underscore and @sailshq/nedb in /server
Bumps [underscore](https://github.com/jashkenas/underscore) and [@sailshq/nedb](https://github.com/sailshq/nedb). These dependencies needed to be updated together.

Updates `underscore` from 1.13.1 to 1.13.8
- [Commits](https://github.com/jashkenas/underscore/compare/1.13.1...1.13.8)

Updates `@sailshq/nedb` from 1.8.3 to 1.8.4
- [Commits](https://github.com/sailshq/nedb/compare/v1.8.3...v1.8.4)

---
updated-dependencies:
- dependency-name: underscore
  dependency-version: 1.13.8
  dependency-type: indirect
- dependency-name: "@sailshq/nedb"
  dependency-version: 1.8.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-18 13:29:02 +00:00
dependabot[bot] d44e0dde93 build(deps): Bump path-to-regexp and @sailshq/router in /server
Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [@sailshq/router](https://github.com/sailshq/router). These dependencies needed to be updated together.

Updates `path-to-regexp` from 0.1.12 to 0.1.13
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/v.0.1.13/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.12...v.0.1.13)

Updates `@sailshq/router` from 1.3.10 to 1.3.11
- [Changelog](https://github.com/sailshq/router/blob/master/HISTORY.md)
- [Commits](https://github.com/sailshq/router/compare/v1.3.10...v1.3.11)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-version: 0.1.13
  dependency-type: indirect
- dependency-name: "@sailshq/router"
  dependency-version: 1.3.11
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-18 13:28:46 +00:00
Daniel Hiller 9a4241e3d1 Merge pull request #1610 from plankanban/dependabot/npm_and_yarn/server/yaml-2.8.3
build(deps): Bump yaml from 2.8.2 to 2.8.3 in /server
2026-04-18 15:27:57 +02:00
Daniel Hiller 5331f590a2 Merge pull request #1617 from plankanban/dependabot/npm_and_yarn/server/brace-expansion-1.1.13
build(deps): Bump brace-expansion from 1.1.12 to 1.1.13 in /server
2026-04-18 15:27:52 +02:00
Daniel Hiller 922d70e289 Merge pull request #1629 from plankanban/dependabot/npm_and_yarn/server/lodash-4.18.1
build(deps): Bump lodash from 4.17.23 to 4.18.1 in /server
2026-04-18 15:27:43 +02:00
Daniel Hiller 40a3e436ad Merge pull request #1608 from plankanban/dependabot/npm_and_yarn/server/picomatch-2.3.2
build(deps): Bump picomatch from 2.3.1 to 2.3.2 in /server
2026-04-18 15:27:22 +02:00
Daniel Hiller 555117912c Merge pull request #1631 from plankanban/dependabot/npm_and_yarn/server/nodemailer-8.0.5
build(deps): Bump nodemailer from 7.0.13 to 8.0.5 in /server
2026-04-18 15:27:11 +02:00
dependabot[bot] 8cc00ef2ef build(deps): Bump fast-xml-parser and @aws-sdk/xml-builder in /server
Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) and [@aws-sdk/xml-builder](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages-internal/xml-builder). These dependencies needed to be updated together.

Updates `fast-xml-parser` from 5.4.1 to 5.5.8
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.4.1...v5.5.8)

Updates `@aws-sdk/xml-builder` from 3.972.11 to 3.972.17
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages-internal/xml-builder/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/HEAD/packages-internal/xml-builder)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-version: 5.5.8
  dependency-type: indirect
- dependency-name: "@aws-sdk/xml-builder"
  dependency-version: 3.972.17
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-09 00:26:02 +00:00
dependabot[bot] 3d3c8f374c build(deps): Bump nodemailer from 7.0.13 to 8.0.5 in /server
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 7.0.13 to 8.0.5.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v7.0.13...v8.0.5)

---
updated-dependencies:
- dependency-name: nodemailer
  dependency-version: 8.0.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-08 22:42:51 +00:00
dependabot[bot] 512b69080d build(deps): Bump lodash from 4.17.23 to 4.18.1 in /server
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.18.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-08 08:21:34 +00:00