Back to Blog
high SEVERITY5 min read

CVE-2026-54673: builder-util-runtime Leaks Auth Headers on Redirect

electron-updater and electron-builder rely on builder-util-runtime to fetch update manifests and artifacts over HTTP. A flaw in that shared HTTP executor allowed credential headers attached to the original update-feed request to be re-sent after a redirect, exposing them to any host the redirect pointed to. The project fixes this by upgrading builder-util-runtime to 9.7.0 and collapsing a duplicate, older copy of the package that electron-updater had pinned on its own.

O
By Orbis AppSec
•Published October 1, 2026•Reviewed October 1, 2026

Answer Summary

builder-util-runtime, the shared HTTP request executor behind electron-updater and electron-builder, was vulnerable before version 9.7.0. An attacker who controls or compromises an update-server redirect target could capture the Authorization/credential headers an app sent to its legitimate update feed, since those headers were resent unchanged to the redirect destination. The fix upgrades builder-util-runtime to 9.7.0, which strips or re-evaluates credential headers before following a redirect, and this project additionally removed a stale duplicate of the package (9.3.1) that electron-updater had vendored separately. CWE classification is not provided in this advisory.

Vulnerability at a Glance

cweunknown
fixUpgrade builder-util-runtime to 9.7.0 and deduplicate the package across the dependency tree
riskUpdate-feed credentials (Authorization headers, tokens) can leak to a redirect target outside the original update host
languageJavaScript/TypeScript (Node.js)
root causeHTTP executor in builder-util-runtime forwarded request headers unchanged when following a redirect response
vulnerabilityInformation disclosure via unstripped credential headers on HTTP redirect

Introduction

electron-updater doesn't talk to update servers directly — it delegates the actual HTTP work to builder-util-runtime, a shared module also used by electron-builder's app-builder-lib. That module's HTTP request executor is responsible for fetching update manifests (latest.yml, latest-mac.yml, etc.) and downloading installer artifacts, often from feeds that require an Authorization header or token to access private releases.

The problem fixed by CVE-2026-54673 sits in how that executor handled HTTP redirects. When an update server responds with a 301/302/307 and a Location header pointing somewhere else, a correctly behaving client should decide whether to keep sending credentials based on whether the redirect target is the same origin. builder-util-runtime's executor didn't make that distinction before 9.7.0: it followed the redirect and resent the same request headers — including any credential header set for the original request — to whatever host the Location pointed to.

For any application using electron-updater against a feed that requires authentication (private GitHub releases, a self-hosted update server behind a token, S3 buckets fronted by signed URLs that redirect, etc.), this meant the credential could leak to a third party if the update host ever redirected cross-origin — whether due to misconfiguration, a CDN migration, or a malicious actor positioned to influence the redirect chain.

Affected Versions

Affected not applicable (first-party code)
Fixed in not applicable (first-party code)
Ecosystem npm
CVE / GHSA CVE-2026-54673 / not assigned
CWE unknown

This finding was flagged against the project's own dependency manifest rather than a published first-party API. In practice, the fix is a dependency bump: builder-util-runtime moves from the vulnerable line (seen in the lockfile as 9.5.1 and a duplicate 9.3.1) to the patched 9.7.0 release.

The Vulnerability Explained

The core issue is a classic redirect-handling mistake: the HTTP executor inside builder-util-runtime treated "follow the redirect" and "resend the same headers" as the same decision. In concrete terms, before 9.7.0 the lockfile pinned two separate copies of the module:

"node_modules/builder-util-runtime": {
  "version": "9.5.1",
"node_modules/electron-updater/node_modules/builder-util-runtime": {
  "version": "9.3.1",

Both of those pre-9.7.0 releases carried the vulnerable redirect behavior in the shared executor that electron-updater calls to fetch update feeds and binaries. Because the executor is reused for both the manifest request and the artifact download, any credential header configured for a private feed — set once by the application when it configures its update URL — rode along on every retry and every redirect hop until the response finally resolved.

Attack scenario: an application configures electron-updater against a private feed, e.g. a GitHub Releases URL that requires a bearer token for a private repository, or an internal update server protected by a static API key sent as Authorization. If that server's response is ever redirected to a different host — a CDN endpoint, a storage bucket, or a host under an attacker's control via DNS/BGP interference or a compromised intermediate proxy — the client faithfully re-sends the Authorization header to the new destination. The operator of that destination (or anyone able to observe traffic to it) now has the application's update credential, which can often be reused to pull private release artifacts or probe other parts of the update infrastructure.

The real-world impact is proportional to how much trust is placed in that token: for apps gating pre-release builds behind a private feed, this is a straightforward credential-theft path triggered simply by the update check that already runs on every app launch.

The Fix

The fix is a dependency version bump plus a dependency-tree cleanup — no application source code changes:

-      "version": "9.5.1",
+      "version": "9.7.0",

and the removal of the stale duplicate electron-updater had vendored on its own:

-    "node_modules/electron-updater/node_modules/builder-util-runtime": {
-      "version": "9.3.1",

To make sure no other package in the tree could silently pull back in an older, vulnerable copy, package.json now pins the fix with explicit overrides:

"overrides": {
  "app-builder-lib": {
    "builder-util-runtime": "9.7.0"
  },
  "builder-util": {
    "builder-util-runtime": "9.7.0"
  },
  "builder-util-runtime": {
    "builder-util-runtime": "9.7.0"
  }
}

Each override entry matters for a different reason: app-builder-lib and builder-util both depend on builder-util-runtime independently and could otherwise resolve to their own historical pin; the builder-util-runtime self-override guarantees even nested resolutions converge on 9.7.0. Combined with deleting the duplicate 9.3.1 entry that electron-updater carried in its own subtree, this closes every path by which the vulnerable redirect-handling code could still end up in node_modules.

Key Takeaways

  • A single shared HTTP executor (builder-util-runtime) is used by both electron-updater and electron-builder's app-builder-lib — a flaw there affects every consumer, not just the update-check path you're actively testing.
  • Credential headers configured for an update feed are not automatically scoped to the original origin; redirect-following HTTP clients must explicitly decide to drop or keep them per-hop.
  • Dependency duplication (electron-updater silently vendoring its own builder-util-runtime@9.3.1 alongside the top-level 9.5.1) can let a vulnerable version survive a top-level upgrade — check nested node_modules entries, not just the root dependency.
  • npm overrides is the right tool to force convergence on a patched transitive dependency across multiple direct dependents at once.

How Orbis AppSec Detected This

  • Source: the Authorization/credential header attached by the application when configuring electron-updater's update feed request
  • Sink: builder-util-runtime's HTTP request executor re-issuing the request to the Location of a redirect response
  • Missing control: no origin comparison between the original request host and the redirect target before resending credential headers
  • CWE: unknown (not classified in this advisory)
  • Fix: upgrade builder-util-runtime to 9.7.0 and enforce that version across the dependency tree via overrides

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-54673 is a reminder that an update mechanism's HTTP plumbing deserves the same scrutiny as any other code path that handles credentials. electron-updater's reliance on builder-util-run

Prevention and further reading

Frequently Asked Questions

Does upgrading builder-util-runtime to 9.7.0 change anything in electron-updater's `autoUpdater` API that app developers call?

No. The fix is contained entirely inside the HTTP request executor that builder-util-runtime provides; `autoUpdater.checkForUpdates()` and related methods behave the same from the caller's perspective.

Why did the lockfile diff show two different versions of builder-util-runtime (9.5.1 and 9.3.1) before the fix?

electron-updater had its own nested copy of builder-util-runtime pinned at 9.3.1, separate from the top-level 9.5.1 copy used elsewhere. The fix removes that duplicate entry and forces a single 9.7.0 copy across the tree.

Which part of the fix actually guarantees every transitive dependency uses the patched version?

The `overrides` block added to `package.json`, which pins `app-builder-lib`, `builder-util`, and `builder-util-runtime` itself to version 9.7.0 regardless of what each package's own `package.json` would otherwise resolve to.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #1

Related Articles

critical

i18next-fs-backend 2.6.4 Prototype Pollution via Crafted Missing-Key

A critical prototype pollution vulnerability in i18next-fs-backend 2.6.4 allows attackers to modify Object.prototype through maliciously crafted translation key strings. The fix upgrades the package from 2.6.4 to 2.6.6, eliminating the unsafe key handling that permitted this attack vector.

high

image-size 1.2.1 DoS: Zero-Valued Dimensions in Image Buffer Parser

A high-severity denial-of-service vulnerability in image-size 1.2.1 allows attackers to crash Node.js services using malicious image buffers with zero-valued dimensions. The fix removes the vulnerable `queue` dependency and tightens dimension validation in version 2.0.3.

high

linkify-it 5.0.1 mailto: Link Parsing Causes DoS

linkify-it versions up to 5.0.1 can be forced into excessive processing time when autolinking a specially crafted mailto: link, allowing a remote attacker to degrade or stall the parsing thread. Upgrading to linkify-it 5.0.2 closes the issue; any application that runs linkify-it (directly or via markdown-it) against untrusted text should update immediately.

critical

Slim CLI Unverified Remote Fetch in Version Check

The Slim CLI's version check command fetched remote package metadata without integrity verification, enabling attackers to serve malicious responses through repository hijacking or man-in-the-middle attacks. The fix adds input validation, HTTP status checking, and response schema verification to ensure only legitimate version data is processed.

critical

ensureTrivy() CWE-494: Unverified Trivy Binary Download

The `ensureTrivy()` function fetched the Trivy vulnerability scanner from GitHub releases without verifying its integrity, exposing applications to supply-chain attacks. An attacker in a MITM position or a compromised CDN could substitute a malicious binary that executes with the application's privileges. The fix adds cryptographic verification using SHA256 checksums published alongside each release.

high

js-yaml 5.2.1 DoS: Exponential Parsing in Flow Collections

A denial-of-service vulnerability in js-yaml 5.2.1 allows an attacker to crash the parser by supplying deeply nested flow collections that trigger exponential parsing behavior. The fix in version 5.2.2 improves the parser's handling of these structures, preventing the algorithmic complexity attack. This is critical for any service accepting user-controlled YAML input.