github vendurehq/vendure v3.8.1

3 hours ago

Vendure v3.8.1 is a patch release containing fixes for three reported vulnerabilities (one high, two low), along with a batch of core, dashboard, job queue and @vendure/create fixes.

If you read job data through the Admin API, or you parse server logs or GraphQL error responses, read Behaviour Changes.

Security

Fixes for the following reported vulnerabilities are in 3.8.1. If you are on an earlier version, upgrade.

Severity Vulnerability Advisory
High Credentials in Admin API job data: the job, jobs and jobsById queries returned job data as it was stored, including email verification, password-reset and email-change tokens and other credential-like values. The telemetry plugin recorded the same data in the job.data span attribute GHSA-hxvp-ff3g-qcj7
Low Stack traces in GraphQL error responses: when NODE_ENV was not production, requests rejected before GraphQL execution got an error response with a stack trace, which exposed server file paths GHSA-qmrg-wpxj-c482
Low GraphiQL plugin asset paths: the asset server answered differently for existing and missing files outside its assets directory, so it showed whether a file existed on the server GHSA-fw8w-3xpv-rg9p

The advisory for GHSA-hxvp-ff3g-qcj7 lists what to do after upgrading. Our thanks to the researchers who reported these responsibly.

Core

  • Updating the Assets of a Product, ProductVariant or Collection no longer removes its Assets in other Channels, or clears a featured Asset which belongs to another Channel (#5639, closes #5629).
  • Channels are looked up by token and cached per token, instead of loading and refreshing every Channel in every process (#5248, relates to #988). Installs with many Channels use less memory and run smaller queries.
  • The inverse sides of many-to-many relations declare their foreign key rules explicitly (#5597, closes #5594). TypeORM 1.1.1 changed the default for these rules, so on TypeORM 1.1.2 runMigrations reported 21 core junction-table foreign keys as out of sync. The schema does not change.
  • Only one root Collection is created, in the default Channel. Before, if the first request after a process start came from another Channel, a second root Collection could be created there (#5587, closes #5584).
  • CollectionService.delete() removes the Collection's variant links inside the request transaction, and unlinks the variants of each descendant from that descendant rather than from the root (#5554, closes #5553).
  • Order totals are calculated from freshly loaded surcharges, so a surcharge added or removed by a blocking event handler is included (#5370, closes #5332).
  • assignProductVariantsToChannel also assigns the variants' ProductOptions and ProductOptionGroups, so ProductOption.group resolves in the target Channel (#5557, closes #5556).
  • Soft-deleted ProductOptions are skipped when assigning a Product to a Channel (#5493), and are rejected as variant option ids by createProductVariants and updateProductVariants (#5613, closes #5602).
  • Customers created by external authentication have their email address normalized, like every other way of creating a Customer (#5583, closes #5559).
  • createFacetValue and createFacetValues no longer load every existing value of the Facet, so creating a value no longer gets slower as the Facet grows (#5506, closes #5497).
  • Relation custom fields set by their input key (<name>Id or <name>Ids) no longer log a false "Custom field not found" warning (#5563, closes #5543).
  • The validate function of list custom fields is typed with its injector and ctx arguments (#5578, closes #5575).
  • No ERR_HTTP_HEADERS_SENT error when an authorization guard finishes after the response was sent (#5520, closes #5519).
  • The Admin API job, jobsById and cancelJob operations find BullMQ jobs with custom ids (#5577, closes #5558).

Dashboard

  • Signing in from the login page, or after a session has expired, no longer overwrites your stored user settings with the defaults (#5644, closes #5595).
  • List tables select the fields of every visible column, so a column which is hidden by default, such as SKU in the variants table, shows its values when you turn it on (#5645, closes #5619).
  • An Administrator whose roles give access to no Channel gets an error message instead of an endless loading screen (#5620, closes #5617).
  • After switching user, the navigation shows the new user's permitted entries without a reload (#5624, closes #5623).
  • Extension pages no longer fail with "useChannel must be used within a ChannelProvider" in useExperimentalBundle mode (#5643).
  • A relative build outDir is resolved against your Vite root, so builds started from another directory, as NX does, land in the right place (#5410, closes #4053).
  • Messages with counts use proper plurals in every locale (#5483, closes #5482).
  • The "Explore Platform & Cloud" user menu entry is renamed "Plans" (#5582).

CLI and @vendure/create

  • Projects created with npm 12 allowlist the install scripts of their native dependencies, so bcrypt, better-sqlite3, esbuild and re2 build (#5566).
  • Scaffolded projects enable EmailPlugin devMode only when APP_ENV is dev. .env is added to .gitignore and to a new .dockerignore, and the Dockerfile sets NODE_ENV=production (#5498). EmailPlugin logs a warning at startup when devMode is on and NODE_ENV is production.
  • The scaffolded Dockerfile uses node:24, as Node.js 20 is end-of-life (#5637).
  • vendure add has a new first entry, and @vendure/create a new question, for starting a Vendure Platform trial (#5608). vendure add --platform starts the same flow.
  • @vendure/create, and vendure dev in a project which is not linked to Console, print one line pointing to Vendure pricing and vendure console link (#5580).
  • vendure console link sends the telemetry installation id to Console when telemetry is on, so Console can attribute the installation's telemetry to the linked Project (#5581).

Plugins

  • Job Queue Plugin:
    • BullMQJobQueueStrategy uses a Redis or Cluster instance passed as connection, instead of treating it as options (#5612, closes #5603).
    • Cancelling a job is scoped to the queue prefix, so instances which share a Redis server with different prefixes no longer cancel each other's jobs (#5524, closes #5518).
    • BullMQJobQueueStrategy (#5526, closes #5525) and RedisJobBufferStorageStrategy (#5610, closes #5601) close the Redis connections they opened when they are destroyed. A connection you passed in is left open.
  • Asset Server Plugin: a newly generated image is sent with the configured Cache-Control header (#5573).
  • Email Plugin: the raw file transport writes its output without crashing the process running the send-email queue (#5574, closes #5571).

Behaviour Changes

No APIs are removed or renamed.

Job data in the Admin API. Job.data, Job.result and Job.error return a redacted copy. Email template variables and credential values show [redacted], and email attachments show only filename and contentType. The telemetry plugin's job.data span attribute holds only the key names of the job data.

Stack traces. GraphQL error responses never include stack traces, whatever NODE_ENV is set to. The adminApiDebug and shopApiDebug options were already deprecated no-ops in 3.8.0.

Startup output. The server and the worker print a Vendure Platform banner at the end of startup (#5606). In an interactive terminal with the default logger it is a box. Without a TTY, in CI, or with a custom logger such as a JSON logger, it is one Logger.info line on every start.

Migration

No database migrations are required. Upgrade all @vendure/* packages together to 3.8.1.

What's Changed

  • chore(repo): normalize repository.url in package manifests by @michaelbromley in #5550
  • chore(dev-server): disable the reviews example plugin by default by @michaelbromley in #5549
  • test(core): read variant prices from the catalog in the price calculation strategy spec by @michaelbromley in #5551
  • docs: rewrite the readme intro for the plans launch by @Itsayaboi in #5480
  • docs: add a header row to the readme feature table by @Itsayaboi in #5560
  • docs: add secret fields guide to the docs navigation by @michaelbromley in #5561
  • fix(core): delete collection variant links inside the request transaction by @brmk in #5554
  • fix(dashboard): resolve relative build outDir against the user's vite root (#4053) by @wakqasahmed in #5410
  • fix(create): allowlist native dependency install scripts for npm 12 by @michaelbromley in #5566
  • chore(repo): include multi-scope and re-applied commits in the changelog by @michaelbromley in #5552
  • chore: remove temporary OpenTelemetry minimumReleaseAge exclusions by @michaelbromley in #5567
  • fix(core): look up channels by token instead of caching every channel by @rafabernad in #5248
  • feat(dashboard): rename the pricing menu entry to Plans by @dlhck in #5582
  • feat(create): print one pricing hint after install by @dlhck in #5580
  • feat(cli): attribute Core telemetry to the Console Project on console link by @dlhck in #5581
  • fix(core,job-queue-plugin): find BullMQ jobs with custom ids in the A… by @Ryrahul in #5577
  • fix(core): don't load a facet's existing values when creating a facet value by @AyeshaWaseemAhmad in #5506
  • fix(core): skip session header writes after response headers are sent by @allanmongej in #5520
  • fix(core): skip soft-deleted options when assigning a product to a channel by @casperiv0 in #5493
  • fix(core): type the injector and ctx args of validate on list custom … by @Ryrahul in #5578
  • fix(core): accept relation custom field input keys in CustomFieldsValidationSubscriber by @Haridass30 in #5563
  • fix(email-plugin): write raw file transport output from the returned buffer by @Haridass30 in #5574
  • fix(asset-server-plugin): apply Cache-Control to newly generated images by @Hen2609 in #5573
  • fix(dashboard): use ICU plurals for counted messages by @theluckystrike in #5483
  • fix(core): normalize the email address of customers created by extern… by @Ryrahul in #5583
  • docs: correct how requiresPermission applies in the Shop API by @gabriellbui in #5570
  • docs: rename Vendure Core to Vendure Framework by @dlhck in #5593
  • test(cli): cover login isolation between config directories by @oliverstreissi in #5591
  • docs: rename Vendure Core to Vendure Framework in core concepts title by @dlhck in #5599
  • fix(core): assign variant options and option groups in assignProductVariantsToChannel by @Haridass30 in #5557
  • fix(job-queue-plugin): close the redis connections the bullmq strategy opens on destroy by @AyeshaWaseemAhmad in #5526
  • fix(core): resolve the root collection in the default channel by @Haridass30 in #5587
  • fix(core): declare inverse junction FK rules explicitly on many-to-many relations by @michaelbromley in #5597
  • feat(cli): add a Vendure Platform trial entry to vendure add and @vendure/create by @dlhck in #5608
  • fix(core): reload surcharges before recalculating order totals by @Ismatulla in #5370
  • feat(dashboard): add a build-time Platform catalog data layer by @dlhck in #5607
  • fix(job-queue-plugin): scope bullmq job cancellation to the queue prefix by @AyeshaWaseemAhmad in #5524
  • fix(create): enable email devMode only in development by @HouseinIsProgramming in #5498
  • fix(job-queue-plugin): close the redis connection of the job buffer storage strategy on destroy by @AyeshaWaseemAhmad in #5610
  • fix(job-queue-plugin): use a Redis or Cluster instance passed as connection by @AyeshaWaseemAhmad in #5612
  • fix(dashboard): show the permitted navigation after switching user without a reload by @Ryrahul in #5624
  • fix(core): ignore deleted product options when validating variant option ids by @AyeshaWaseemAhmad in #5613
  • revert(dashboard): move the Platform catalog data layer to the next minor by @dlhck in #5633
  • feat(core): show a Vendure Platform banner after server and worker startup by @dlhck in #5606
  • ci: resolve back-merge conflicts in the generated docs manifest automatically by @dlhck in #5636
  • fix(create): use Node 24 in the scaffolded Dockerfile by @michaelbromley in #5637
  • fix(graphiql-plugin): call vite directly in the build script by @michaelbromley in #5638
  • fix(core): keep the assets of other channels when updating the assets… by @Ryrahul in #5639
  • fix(dashboard): prevent duplicate module instances in experimental bundle mode by @michaelbromley in #5643
  • fix(dashboard): keep stored user settings when signing in from a signed-out page by @michaelbromley in #5644
  • fix(dashboard): select list query fields from the table's live column visibility by @michaelbromley in #5645
  • docs: list Node.js 22, 24 and 26 as supported and mark Node.js 20 as end-of-life by @michaelbromley in #5648
  • fix(dashboard): show an error instead of an endless loading screen fo… by @Ryrahul in #5620

New Contributors

Full Changelog: v3.8.0...v3.8.1

Don't miss a new vendure release

NewReleases is sending notifications on new releases.