CVE-2026-54673: electron-updater Cross-origin Redirect Leaks `PRIVATE-TOKEN` And Vulnerability

HIGH
Advisory Identifier: GHSA-p2f4-r6v6-j797
CWE-200
Published
Advisory Summary

CVE-2026-54673 is a HIGH cross-origin redirect leaks `private-token` and vulnerability (CWE-200: Exposure of Sensitive Information to an Unauthorized Actor) affecting electron-updater libraries in the npm ecosystem. The issue involves cross-origin redirect leaks `private-token` and mixed-case `authorization` credentials in `builder-util-runtime`. Remediation is available by upgrading affected packages to version 9.7.0.

CVE-2026-54673 at a Glance

CVE Identifier CVE-2026-54673
GHSA Identifier GHSA-p2f4-r6v6-j797
Severity HIGH
CVSS v3.1 Base Score N/A
CWE Classification CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
Affected Product electron-updater
Package Ecosystem npm
Published Date
Last Updated

How to Fix CVE-2026-54673

To remediate this vulnerability, upgrade all affected electron-updater dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

builder-util-runtime fixed: 9.7.0
npm install builder-util-runtime@9.7.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls builder-util-runtime

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-54673, inspect your project dependencies using npm:

npm ls builder-util-runtime

Analyze the terminal output to locate any version of electron-updater in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 9.7.0), your application is affected.

Note: The npm ls builder-util-runtime command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor, where the product exposes sensitive information to an actor that is not explicitly authorized to have access to that information. In electron-updater, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary In `electron-builder`'s `builder-util-runtime` package, the HTTP redirect handler (`HttpExecutor.prepareRedirectUrlOptions`) only stripped a credential header whose key string matched exactly lowercase `"authorization"`. Other credential-bearing headers — most notably `PRIVATE-TOKEN` (used by GitLab's personal access token flow) and mixed-case `Authorization` (used by GitLab's Bearer/OAuth flow) — were not stripped and could be forwarded to an attacker-controlled cross-origin redirect destination. --- ## Details ### Root cause `HttpExecutor.prepareRedirectUrlOptions` (introduced in `builder-util-runtime` via [PR #9211](https://github.com/electron-userland/electron-builder/pull/9211), first released in `v26.0.20`) performed its cross-origin credential strip with a single case-sensitive property check: ```typescript // vulnerable code (electron-builder v26.0.20 – v26.14.x) [via builder-util-runtime <9.7.0] if (headers?.authorization) { if (HttpExecutor.isCrossOriginRedirect(originalUrl, parsedRedirectUrl)) { delete headers.authorization // only removes the exact key "authorization" } } ``` JavaScript object property access is case-sensitive. The guard `headers?.authorization` evaluates to `undefined` (falsy) when the key is `"Authorization"`, `"AUTHORIZATION"`, or any other casing, so the branch is never entered and **no header is deleted** for those cases. ### Affected updater flows The clearest reproduced path is the private GitLab updater flow. `packages/electron-updater/src/providers/GitLabProvider.ts` sets one of two credential headers depending on the token type: ```typescript // GitLabProvider.setAuthHeaderForToken (affected versions) if (token.startsWith("Bearer")) { headers.authorization = token // Bearer / OAuth token → key is lowercase } else { headers["PRIVATE-TOKEN"] = token // personal access token → key is "PRIVATE-TOKEN" } ``` During a private release update check, the updater requests a release asset through GitLab's `direct_asset_url`. GitLab commonly redirects asset downloads to an external object-storage origin (e.g., S3, GCS). Because the redirect crosses origins: 1. A personal access token in `PRIVATE-TOKEN` **is never inspected** by the vulnerable strip guard — it is forwarded intact. 2. A Bearer token set as `headers.authorization` (lowercase) **is stripped** correctly. 3. A Bearer token set as `headers.Authorization` (capital A) or any other mixed-case variant **bypasses the guard** and is forwarded intact. GitLab is the concrete reproduced case; any other provider or custom updater configuration that places credentials in a non-lowercase-`authorization` header is equally affected. ### Before v26.0.20 Versions prior to `v26.0.20` did not contain `prepareRedirectUrlOptions` at all. All credential headers were forwarded unchanged on every redirect, regardless of origin. This represents a broader, pre-existing version of the same class of vulnerability. --- ## Proof of concept (reproduction shape) 1. Configure the updater with an authenticated GitLab provider, supplying a personal access token (non-Bearer). The provider will set `PRIVATE-TOKEN: <token>` on requests. 2. Trigger an update check. The updater fetches release metadata and then requests a release asset URL. 3. The trusted GitLab origin returns a 3xx cross-origin redirect (e.g., to S3 object storage). 4. `HttpExecutor.prepareRedirectUrlOptions` is called. The guard `headers?.authorization` is falsy (the key is `"PRIVATE-TOKEN"`). No header is deleted. 5. The request to the redirect destination is issued with `PRIVATE-TOKEN: <token>` present in the headers. **Observed result:** The personal access token is forwarded to the redirect destination. An attacker who controls or can observe the redirect destination receives the token. --- ## Impact This is a credential disclosure vulnerability. An automatic update check can leak: - GitLab personal access tokens (`PRIVATE-TOKEN`) - Bearer/OAuth tokens sent under a mixed-case `Authorization` key - Any other credential header not named exactly `"authorization"` in lowercase Disclosure of a GitLab PAT grants the attacker whatever repository and API permissions the token carries, enabling unauthorized access to private source code, packages, or release artifacts. --- ## Patches Fixed in electron-builder `v26.15.0` [included via `v9.7.0` `builder-util-runtime`] via [PR #9834](https://github.com/electron-userland/electron-builder/pull/9834) (commit [`22a7532bd`](https://github.com/electron-userland/electron-builder/commit/22a7532bd01b9fb42cff7c58d599c7ad683569fe)). The incomplete property-access guard was replaced with a separator-agnostic, case-insensitive lookup against a registry of known sensitive header names: ```typescript // fixed code (v9.7.0+) const normalizeName = (name: string): string => name.toLowerCase().replace(/[-_]/g, "") const SENSITIVE_REDIRECT_HEADERS = new Set([ "authorization", "proxyauthorization", "privatetoken", "xapikey", "xauthtoken", "xaccesstoken", "xgitlabtoken", "cookie", "xcsrftoken", ]) // In prepareRedirectUrlOptions, on cross-origin redirect: for (const key of Object.keys(headers)) { if (SENSITIVE_REDIRECT_HEADERS.has(normalizeName(key))) { delete (headers as Record<string, unknown>)[key] } } ``` `normalizeName` converts to lowercase and strips `-` and `_` separators, so `PRIVATE-TOKEN`, `Private-Token`, `Authorization`, `AUTHORIZATION`, `X-Api-Key`, etc. are all matched. The fix also exports `addSensitiveRedirectHeader()` to allow custom publishers to register additional headers. **Upgrade path:** Update `builder-util-runtime` to `>= 9.7.0`. --- ## Workarounds There is no configuration-level workaround that prevents header forwarding in affected versions. The only mitigation short of upgrading is to avoid authenticated GitLab updater flows on versions `< 9.7.0`. If operating in a network environment where you control all possible redirect destinations, you may be able to prevent the token from reaching an attacker-controlled host through network-layer controls, but this is not a reliable mitigation.

CVE-2026-54673 Affected electron-updater Versions

1 component(s)
Fixed Versions:
9.7.0
Product / Package Ecosystem Affected Versions Fixed Version
builder-util-runtime
npm
< 9.7.0
9.7.0

References

Frequently Asked Questions

What is CVE-2026-54673?
CVE-2026-54673 is a security vulnerability in electron-updater involving Cross-origin redirect leaks `PRIVATE-TOKEN` and mixed-case `Authorization` credentials in `builder-util-runtime` under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor.
Which electron-updater versions are affected?
Affected versions include releases prior to 9.7.0 across affected packages: builder-util-runtime.
What version fixes CVE-2026-54673?
Upgrading to 9.7.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is builder-util-runtime affected?
Yes, builder-util-runtime is affected in releases prior to 9.7.0. Upgrade your dependency to 9.7.0 or later.
What CWE is associated with CVE-2026-54673?
CVE-2026-54673 is classified under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor (The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.).
How can I check npm dependencies for CVE-2026-54673?
Run the dependency tree command: 'npm ls builder-util-runtime'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-p2f4-r6v6-j797",
  "modified" : "2026-07-24T14:03:19Z",
  "published" : "2026-07-24T14:03:19Z",
  "aliases" : [ "CVE-2026-54673" ],
  "summary" : "electron-updater: Cross-origin redirect leaks `PRIVATE-TOKEN` and mixed-case `Authorization` credentials in `builder-util-runtime`",
  "details" : "## Summary\n\nIn `electron-builder`'s `builder-util-runtime` package, the HTTP redirect handler (`HttpExecutor.prepareRedirectUrlOptions`) only stripped a credential header whose key string matched exactly lowercase `\"authorization\"`. Other credential-bearing headers — most notably `PRIVATE-TOKEN` (used by GitLab's personal access token flow) and mixed-case `Authorization` (used by GitLab's Bearer/OAuth flow) — were not stripped and could be forwarded to an attacker-controlled cross-origin redirect destination.\n\n---\n\n## Details\n\n### Root cause\n\n`HttpExecutor.prepareRedirectUrlOptions` (introduced in `builder-util-runtime` via [PR #9211](https://github.com/electron-userland/electron-builder/pull/9211), first released in `v26.0.20`) performed its cross-origin credential strip with a single case-sensitive property check:\n\n```typescript\n// vulnerable code (electron-builder v26.0.20 – v26.14.x) [via builder-util-runtime <9.7.0]\nif (headers?.authorization) {\n  if (HttpExecutor.isCrossOriginRedirect(originalUrl, parsedRedirectUrl)) {\n    delete headers.authorization   // only removes the exact key \"authorization\"\n  }\n}\n```\n\nJavaScript object property access is case-sensitive. The guard `headers?.authorization` evaluates to `undefined` (falsy) when the key is `\"Authorization\"`, `\"AUTHORIZATION\"`, or any other casing, so the branch is never entered and **no header is deleted** for those cases.\n\n### Affected updater flows\n\nThe clearest reproduced path is the private GitLab updater flow.\n\n`packages/electron-updater/src/providers/GitLabProvider.ts` sets one of two credential headers depending on the token type:\n\n```typescript\n// GitLabProvider.setAuthHeaderForToken (affected versions)\nif (token.startsWith(\"Bearer\")) {\n  headers.authorization = token        // Bearer / OAuth token  →  key is lowercase\n} else {\n  headers[\"PRIVATE-TOKEN\"] = token     // personal access token →  key is \"PRIVATE-TOKEN\"\n}\n```\n\nDuring a private release update check, the updater requests a release asset through GitLab's `direct_asset_url`. GitLab commonly redirects asset downloads to an external object-storage origin (e.g., S3, GCS). Because the redirect crosses origins:\n\n1. A personal access token in `PRIVATE-TOKEN` **is never inspected** by the vulnerable strip guard — it is forwarded intact.\n2. A Bearer token set as `headers.authorization` (lowercase) **is stripped** correctly.\n3. A Bearer token set as `headers.Authorization` (capital A) or any other mixed-case variant **bypasses the guard** and is forwarded intact.\n\nGitLab is the concrete reproduced case; any other provider or custom updater configuration that places credentials in a non-lowercase-`authorization` header is equally affected.\n\n### Before v26.0.20\n\nVersions prior to `v26.0.20` did not contain `prepareRedirectUrlOptions` at all. All credential headers were forwarded unchanged on every redirect, regardless of origin. This represents a broader, pre-existing version of the same class of vulnerability.\n\n---\n\n## Proof of concept (reproduction shape)\n\n1. Configure the updater with an authenticated GitLab provider, supplying a personal access token (non-Bearer). The provider will set `PRIVATE-TOKEN: <token>` on requests.\n2. Trigger an update check. The updater fetches release metadata and then requests a release asset URL.\n3. The trusted GitLab origin returns a 3xx cross-origin redirect (e.g., to S3 object storage).\n4. `HttpExecutor.prepareRedirectUrlOptions` is called. The guard `headers?.authorization` is falsy (the key is `\"PRIVATE-TOKEN\"`). No header is deleted.\n5. The request to the redirect destination is issued with `PRIVATE-TOKEN: <token>` present in the headers.\n\n**Observed result:** The personal access token is forwarded to the redirect destination. An attacker who controls or can observe the redirect destination receives the token.\n\n---\n\n## Impact\n\nThis is a credential disclosure vulnerability. An automatic update check can leak:\n\n- GitLab personal access tokens (`PRIVATE-TOKEN`)\n- Bearer/OAuth tokens sent under a mixed-case `Authorization` key\n- Any other credential header not named exactly `\"authorization\"` in lowercase\n\nDisclosure of a GitLab PAT grants the attacker whatever repository and API permissions the token carries, enabling unauthorized access to private source code, packages, or release artifacts.\n\n---\n\n## Patches\n\nFixed in electron-builder `v26.15.0` [included via `v9.7.0` `builder-util-runtime`] via [PR #9834](https://github.com/electron-userland/electron-builder/pull/9834) (commit [`22a7532bd`](https://github.com/electron-userland/electron-builder/commit/22a7532bd01b9fb42cff7c58d599c7ad683569fe)).\n\nThe incomplete property-access guard was replaced with a separator-agnostic, case-insensitive lookup against a registry of known sensitive header names:\n\n```typescript\n// fixed code (v9.7.0+)\nconst normalizeName = (name: string): string =>\n  name.toLowerCase().replace(/[-_]/g, \"\")\n\nconst SENSITIVE_REDIRECT_HEADERS = new Set([\n  \"authorization\", \"proxyauthorization\", \"privatetoken\",\n  \"xapikey\", \"xauthtoken\", \"xaccesstoken\", \"xgitlabtoken\",\n  \"cookie\", \"xcsrftoken\",\n])\n\n// In prepareRedirectUrlOptions, on cross-origin redirect:\nfor (const key of Object.keys(headers)) {\n  if (SENSITIVE_REDIRECT_HEADERS.has(normalizeName(key))) {\n    delete (headers as Record<string, unknown>)[key]\n  }\n}\n```\n\n`normalizeName` converts to lowercase and strips `-` and `_` separators, so `PRIVATE-TOKEN`, `Private-Token`, `Authorization`, `AUTHORIZATION`, `X-Api-Key`, etc. are all matched. The fix also exports `addSensitiveRedirectHeader()` to allow custom publishers to register additional headers.\n\n**Upgrade path:** Update `builder-util-runtime` to `>= 9.7.0`.\n\n---\n\n## Workarounds\n\nThere is no configuration-level workaround that prevents header forwarding in affected versions. The only mitigation short of upgrading is to avoid authenticated GitLab updater flows on versions `< 9.7.0`.\n\nIf operating in a network environment where you control all possible redirect destinations, you may be able to prevent the token from reaching an attacker-controlled host through network-layer controls, but this is not a reliable mitigation.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "builder-util-runtime"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "9.7.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/electron-userland/electron-builder/security/advisories/GHSA-p2f4-r6v6-j797"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-54673"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/electron-userland/electron-builder/pull/9834"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/electron-userland/electron-builder/commit/22a7532bd01b9fb42cff7c58d599c7ad683569fe"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/electron-userland/electron-builder"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/electron-userland/electron-builder/releases/tag/electron-builder@26.15.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-24T14:03:19Z",
    "nvd_published_at" : "2026-06-30T23:17:28Z"
  }
}