Skip to content

fix: upgrade builder-util-runtime to 9.7.0 (CVE-2026-54673) - #86

Merged
abasiri merged 2 commits into
doctly:mainfrom
anupamme:fix-repo-switchboard-cve-2026-54673-builder-util-runtime
Aug 1, 2026
Merged

fix: upgrade builder-util-runtime to 9.7.0 (CVE-2026-54673)#86
abasiri merged 2 commits into
doctly:mainfrom
anupamme:fix-repo-switchboard-cve-2026-54673-builder-util-runtime

Conversation

@anupamme

@anupamme anupamme commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Switch from overrides-based fix to a minimal electron-updater bump to resolve CVE-2026-54673 (GHSA-p2f4-r6v6-j797).

Vulnerability

CVE-2026-54673 / GHSA-p2f4-r6v6-j797builder-util-runtime < 9.7.0 (CVSS 4.0: 8.2 HIGH, CWE-200)

HttpExecutor.prepareRedirectUrlOptions stripped credential headers using a case-sensitive property check:

// vulnerable
if (headers?.authorization) {          // only matches exact lowercase key
  if (HttpExecutor.isCrossOriginRedirect(...)) {
    delete headers.authorization
  }
}

This meant PRIVATE-TOKEN (GitLab personal access token flow) and mixed-case Authorization keys were never inspected — they passed the guard and were forwarded intact to cross-origin redirect destinations.

Concrete path: During an auto-update check against a private GitLab release, electron-updater requests asset URLs. GitLab commonly redirects asset downloads cross-origin (to S3/GCS). Any credential in PRIVATE-TOKEN or a non-lowercase Authorization key is forwarded to the redirect destination, leaking it to anyone who controls or can observe that destination.

Our exposure: electron-updater is a runtime dependency — it ships inside the packaged app and performs update-check requests at runtime. This app uses GitHub releases (not GitLab), so the specific authenticated-GitLab-PAT path isn't exercised. However, builder-util-runtime's redirect handler is shared infrastructure for all provider flows; upgrading to the patched version closes the class of vulnerability regardless of provider. Fixed in builder-util-runtime >= 9.7.0 / electron-builder v26.15.0 via PR #9834.

Approach change (per maintainer review)

The previous commit used overrides: { "builder-util-runtime": "9.7.0" } to force the patched version. This was correctly flagged: all five electron-builder toolchain packages pin builder-util-runtime to exactly 9.5.1, so the override silently applied a version none of them declared compatibility with. If that mismatch broke electron-updater subtly, users couldn't auto-update — a worse failure mode than the CVE itself for a desktop app.

Minimal fix: bump electron-updater to ^6.8.9, drop overrides. electron-updater 6.8.9 natively resolves builder-util-runtime to 9.7.0. The electron-builder devDependency toolchain keeps 9.5.1 under its own nested node_modules/ and is excluded from the packaged app. This is a supported version combination.

Changes

  • package.json: electron-updater ^6.3.0^6.8.9; removed overrides block
  • package-lock.json: regenerated (npm install --package-lock-only); node_modules/builder-util-runtime resolves to 9.7.0; electron-builder toolchain keeps 9.5.1 under nested paths

Verification

Lockfile resolution:

node_modules/builder-util-runtime          → 9.7.0  (electron-updater, ships in app)
node_modules/*/builder-util-runtime        → 9.5.1  (electron-builder devDep toolchain, not shipped)

npm run build:mac passes — packaging confirmed working with the updated dependency tree.


Automated security fix by OrbisAI Security

Automated dependency upgrade by OrbisAI Security
@abasiri

abasiri commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Thanks for catching this — and worth stating up front that it's more relevant than a build-tool CVE usually is. builder-util-runtime reaches us through electron-updater, which is a runtime dependency, so the affected code ships inside the packaged app. It isn't build-only.

That said, I'd like to land it differently, because overrides here is doing more than it looks.

Every consumer pins the version exactly, not as a range:

electron-updater   requires 9.5.1
electron-builder   requires 9.5.1
app-builder-lib    requires 9.5.1
builder-util       requires 9.5.1
electron-publish   requires 9.5.1

So overrides: { "builder-util-runtime": "9.7.0" } forces a version that none of the five declare compatibility with. npm applies it silently. electron-builder versions this toolchain in lockstep, so the exact pin looks deliberate rather than incidental.

The reason I'd rather not force it: electron-updater is the auto-update path. If a mismatch breaks it subtly, the failure mode is that users can't auto-update — including to the fix. That's self-locking, and worse than the CVE for a locally-installed desktop app.

Upstream has already moved, so we don't need to force anything:

electron-updater  6.8.9   → pins builder-util-runtime 9.7.0
electron-builder  26.15.3 → pins builder-util-runtime 9.7.0

I tested both routes locally with npm install --package-lock-only:

Minimal — bump electron-updater to ^6.8.9 only. The shipped copy resolves to 9.7.0 as electron-updater/node_modules/builder-util-runtime, the top level stays 9.5.1 for electron-builder (a devDependency, excluded from the package), and no overrides block is needed. Lockfile churn: 42 insertions / 434 deletions.

Full — also bump electron-builder to ^26.15.3. Single deduped 9.7.0 at the top level, but it moves ~259 packages across the build toolchain (26.8.1 → 26.15.3 is seven minors), so it wants a real packaging test.

My preference is the minimal one: it closes the shipped exposure, is a supported combination, and drops the overrides block entirely. Would you be up for changing the PR to that?

Two asks either way:

  1. Could you add what CVE-2026-54673 actually is, and whether our usage is affected? The title references it but the body doesn't describe the vector, which makes it hard to judge urgency.
  2. Note I only verified dependency resolution, not a full install or packaging run — so whichever route we take should get a npm run build:mac (or CI) before merge.

@anupamme

anupamme commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review; you're right, forcing the override on a toolchain that pins exact versions is riskier than it looks, and breaking auto-update is a much worse failure mode than the CVE itself. I'll switch to the minimal route.

Updated approach: bump electron-updater to ^6.8.9, drop the overrides block entirely. This resolves builder-util-runtime to 9.7.0 under electron-updater/node_modules/, leaves the top-level electron-builder devDependency at 9.5.1 (excluded from the packaged app), and matches a version combination electron-updater's maintainers actually support.

On CVE-2026-54673: [explanation, see below]. Since electron-updater runs at runtime inside the packaged app and performs the update-check requests, our usage is affected.

I'll run npm run build: mac (and update the lockfile via npm install --package-lock-only first) before pushing, and update the PR description with the vector.

Replaces the `overrides: { "builder-util-runtime": "9.7.0" }` approach
with a minimal `electron-updater` bump to `^6.8.9`.

The override forced a version that all five electron-builder toolchain
packages pin exactly to 9.5.1, silently applying an incompatible version.
If the mismatch broke electron-updater subtly, users couldn't auto-update —
worse than the CVE for a desktop app.

electron-updater 6.8.9 natively resolves builder-util-runtime to 9.7.0
under node_modules/electron-updater/; the electron-builder devDep toolchain
keeps 9.5.1 under its own nested paths and is not shipped in the app.
This is a supported version combination with no overrides needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@abasiri
abasiri merged commit b2489df into doctly:main Aug 1, 2026
5 checks passed
abasiri added a commit that referenced this pull request Aug 1, 2026
ws < 8.20.2 has an uninitialized-memory disclosure and a memory-exhaustion DoS
from tiny fragments. ws is a direct production dependency and ships in the
packaged app, so unlike the rest of the current audit output this one reaches
users.

Real-world exposure is narrow: the only consumer is mcp-bridge.js, whose
WebSocketServer binds host 127.0.0.1 behind a UUID auth token and an `mcp`
subprotocol gate, so reaching it needs a local process already running as the
user. Bumping anyway — it is a same-major patch move with no API change.

Verified 8.21.1 still satisfies the bridge: server binds to loopback,
handleProtocols accepts, and a client handshake with subprotocol "mcp"
completes.

For the record on the rest of `npm audit`: 17 of the 19 findings are
electron-builder's own toolchain (tar, lodash, js-yaml, dmg-builder, …), which
runs at package time and is excluded from the app. builder-util-runtime is
flagged only on electron-builder's nested 9.5.1 copies — the shipping copy
resolves to 9.7.0 via electron-updater 6.8.9 (#86). The remaining shipping one
is js-yaml, reachable only through update-feed parsing, i.e. only exploitable
by whoever already controls the release feed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants