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
•Technically reviewed by Anupam Mediratta•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

Lampa Desktop Auto-Update Heuristic Bypass: Execution of Unverified

Lampa Desktop's auto-update mechanism downloaded JavaScript and CSS from `raw.githubusercontent.com` using only heuristic validation—file size thresholds and string pattern matching—that attackers could trivially satisfy. The fix introduces cryptographic integrity verification by cross-referencing Git blob hashes from the GitHub Contents API, ensuring downloaded code matches the repository's authoritative state before execution.

high

adm-zip 0.6.0 Preserves SUID Bits From ZIPs: CVE-2026-102282

The `adm-zip` dependency resolved to 0.6.0 in this project's dependency tree, a version affected by CVE-2026-102282: during extraction it applies the Unix permission bits stored in each ZIP entry's external file attributes verbatim, including the setuid (`04000`), setgid (`02000`), and sticky bits. An attacker who controls an archive passed to `extractAllTo()` or `extractEntryTo()` can therefore have the extractor create a setuid binary owned by whatever user the extraction process runs as. The

high

requestInput() Type Confusion: NaN and Object Bypass in JavaScript

The `requestInput()` utility function lacked validation on its `type` parameter and failed to handle `NaN` results from float conversions, creating a type confusion weakness. An attacker could supply malformed inputs that propagate unhandled `NaN` values or unexpected object types through the type system. The fix adds explicit guards against `NaN` type parameters and rejects non-primitive type values.

critical

No Rate Limit on /api/uploads/presign Enables DoS

The `/api/uploads/presign` endpoint accepted unlimited concurrent requests to generate storage presigned URLs, giving an attacker a free lever to exhaust storage-provider quotas and server resources. The fix adds an `express-rate-limit` middleware capping each client to 30 requests per minute on that route.

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

picomatch 2.3.1 ReDoS: Extglob Pattern Catastrophic Backtracking

picomatch versions below 2.3.2, 3.0.2, or 4.0.4 contain a Regular Expression Denial of Service vulnerability in extglob pattern parsing. An attacker can cause catastrophic backtracking with patterns containing nested alternations and quantifiers, freezing any Node.js process that evaluates untrusted glob expressions.