All posts
Forward Development

Vendure 3.8.1 security patch: what changed and how to upgrade safely

Vendure 3.8.1 fixes a high-severity job data leak and two low issues. What changes in job data, logs and errors, plus an upgrade checklist.

  • Vendure
  • Migrations
  • Operations

Until 3.8.1, anyone who could read your Vendure job queue through the Admin API could also read the password-reset tokens stored in it. That is the high-severity issue in this release. It is the kind of issue that never appears in an incident log, because nothing breaks. A query returns more than it should, and the only trace is whatever someone did with the result. The upgrade is a patch release with no database migrations, so it is small. The real work is finding what in your stack depended on the old behaviour.

3.8.1 fixes three vulnerabilities, one rated high

The release notes say it plainly: if you are on an earlier version, upgrade. 3.8.0 is listed as a recent release, but these fixes ship in 3.8.1. Stopping at 3.8.0 does not close them.

  • High: credentials in Admin API job data (GHSA-hxvp-ff3g-qcj7). The job, jobs and jobsById queries returned job data exactly as it was stored. That included email verification, password-reset and email-change tokens, plus other credential-like values. The telemetry plugin recorded the same data in the job.data span attribute. If you run that plugin, your tracing backend may hold copies too.
  • Low: stack traces in GraphQL error responses (GHSA-qmrg-wpxj-c482). When NODE_ENV was not production, requests rejected before GraphQL execution got an error response with a stack trace, which exposed server file paths.
  • Low: GraphiQL plugin asset paths (GHSA-fw8w-3xpv-rg9p). The asset server answered differently for existing and missing files outside its assets directory, so a caller could tell whether a file existed on the server.

The high-severity issue needs more than a version bump. The advisory for GHSA-hxvp-ff3g-qcj7 lists what to do after upgrading. Read it and follow it; the patch on its own does not close the matter. Our view is that anything every admin role with job access could read, and anything exported to a tracing vendor, should be treated as possibly seen. Find out which roles had job read permissions, where your spans go and how long that backend keeps them.

The second issue is a good prompt to check something regardless of version: staging and preview environments that are reachable from the internet and don't run with NODE_ENV=production.

Job data now comes back redacted

The release notes are clear that no APIs are removed or renamed. Three outputs do change, and this one is the most likely to break something.

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

Code that typically depends on the old output:

  • An admin extension or support page that shows job payloads, such as the template variables of a failed send-email job.
  • Scripts that poll jobs to retry or reconcile failures and branch on values inside data.
  • Integrations that read Job.result to collect the output of a custom job.
  • Tracing dashboards or alerts that filter on values inside job.data.

If anything reads values from job data over the Admin API, rather than just keys, it needs a different source. The clean fix is usually to have the job handler write what you need to your own entity or log when it runs, instead of fetching it back through the Admin API later.

Stack traces and startup output change too

GraphQL error responses never include stack traces now, whatever NODE_ENV is set to. Developers who read traces in the response during local work will need to read them from the server log. End-to-end tests that snapshot GraphQL error bodies from a non-production environment will show diffs. adminApiDebug and shopApiDebug were already deprecated no-ops in 3.8.0. If they are still in your config, take them out.

The server and the worker now print a Vendure Platform banner at the end of startup. 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. That is harmless unless a readiness probe, deploy script or log alert assumes a specific line is the last thing printed at boot, or counts info lines.

Other fixes can look like regressions

These are not security fixes, but they change behaviour you may have worked around:

  • Updating the Assets of a Product, ProductVariant or Collection no longer removes its Assets in other Channels, and no longer clears a featured Asset that belongs to another Channel. Code that re-attaches assets after an edit may now be redundant.
  • Channels are looked up by token and cached per token, instead of every Channel being loaded in every process. Installs with many Channels should see lower memory use.
  • The inverse sides of many-to-many relations now declare their foreign key rules explicitly. On TypeORM 1.1.2, runMigrations had reported 21 core junction-table foreign keys as out of sync. The schema does not change. If you generated a migration to fix that report, review it before it runs anywhere.
  • BullMQJobQueueStrategy now uses a Redis or Cluster instance passed as connection as-is, instead of treating it as options. Cancelling a job is scoped to the queue prefix. The strategy closes the connections it opened, and leaves one you passed in open.
  • New scaffolds use node:24 and set NODE_ENV=production in the Dockerfile. Existing projects don't get these changes, so check your own Dockerfile. EmailPlugin now logs a warning at startup when devMode is on and NODE_ENV is production.

The upgrade checklist

  1. Upgrade every @vendure/* package to 3.8.1 in the same change. The notes say to upgrade them together. Afterwards, check that npm ls --all | grep '@vendure/' shows only one version.
  2. No database migrations are required. Still run your usual schema check against a staging copy, so you can see the TypeORM foreign-key report clear rather than finding a new diff in production.
  3. Search the codebase and any external integrations for the job, jobs and jobsById queries and for reads of data, result or error. Search tracing queries for job.data.
  4. Remove adminApiDebug and shopApiDebug from the config.
  5. Review log parsers, alerts and readiness probes against the new startup output, under both a TTY and your real process manager.
  6. Complete the post-upgrade steps in GHSA-hxvp-ff3g-qcj7.

The test plan

  • In staging, trigger a password reset and an email verification. Query jobs as an administrator and confirm that tokens and template variables read [redacted].
  • If you run the telemetry plugin, open a new span and confirm job.data holds only key names.
  • Set NODE_ENV to something other than production, send a request that fails before execution (a malformed body, for example), and confirm the response has no stack trace.
  • Restart the server and the worker under your real process manager. Confirm health checks pass and no log alert fires on the banner.
  • On a multi-Channel install, edit a product's assets in one Channel and confirm the other Channels keep theirs.
  • If two instances share a Redis server with different prefixes, cancel a job on one and confirm the other is unaffected.

What to do next

Upgrade staging first, run the test plan and promote to production. A patch release with no database migrations is about as cheap as an upgrade gets. Most of the risk is in custom plugins and integrations reading job data, which a short search will find.

If you are planning a move to Vendure from Magento 2 or Adobe Commerce, how a platform publishes security fixes and behaviour changes should count in that decision. This release is a good example of detailed release notes. We cover what to weigh on the Magento 2 / Adobe Commerce to Medusa or Vendure migration page. If you want a second pair of eyes on the upgrade or your custom plugins, get in touch.

Need this done on a real stack?

Magento 2, Adobe Commerce, migrations to Medusa.js or Vendure, enterprise Next.js, WordPress, and AI automation.

Contact us