github electron-userland/electron-builder electron-updater@7.0.0-alpha.9

pre-release4 hours ago

Major Changes

  • Feat(updater): add verifyUpdateFile to AppUpdater, and rename the NSIS Authenticode verification interface #10239 317fc9e @Lemonexe

    AppUpdater.verifyUpdateFile lets an app run its own verification of an update file before that file is allowed to become installable. The default implementation is a stub that immediately succeeds. It runs on every path that can lead to an install — right after a fresh download (while the file still sits under a temporary name, so an unverified file is never executable under its real name), when an update downloaded by an earlier session is reused from the cache, and before an install-on-next-launch spawns the cached installer. On failure the file is deleted and an ERR_UPDATER_INVALID_UPDATE_FILE error is emitted. Assigning null restores the default.

    The NSIS Authenticode verification interface now returns an unambiguous result object instead of the null-means-success / string-means-error convention:

    type VerifyUpdateFileResult =
      | { response: "success" }
      | { response: "failure"; message: string };

    BREAKING CHANGE: NsisUpdater.verifyUpdateCodeSignature is deprecated in favour of verifyUpdateFileAuthenticodeSignature, which differs in return type. The old name is kept as a compatibility shim that translates in both directions and shall be removed in electron-builder v28.

    // Before
    autoUpdater.verifyUpdateCodeSignature = async (publisherNames, path) =>
      isValid ? null : "why it failed";
    
    // After
    autoUpdater.verifyUpdateFileAuthenticodeSignature = async (
      publisherNames,
      path
    ) =>
      isValid
        ? { response: "success" }
        : { response: "failure", message: "why it failed" };

    BREAKING CHANGE: the protected NsisUpdater._verifyUpdateCodeSignature member is renamed to _verifyUpdateFileAuthenticodeSignature and takes the new return type. A deprecated accessor under the old name forwards to it, so a subclass that assigns this._verifyUpdateCodeSignature keeps working; a subclass that redeclares it as a class field shadows the accessor and must be migrated.

    BREAKING CHANGE: the protected BaseUpdater.verifyInstallerSignatureOnLaunch returns Promise<VerifyUpdateFileResult> instead of Promise<string | null>. An override that resolves null to mean "verified" now reports every install-on-next-launch as unsigned; return { response: "success" } instead. (This member was introduced earlier in the same v27 pre-release cycle, so only apps on a 7.0.0-alpha are affected.)

  • Feat!: electron-updater sends update-feed credentials only to downloads on the feed's origin. With the generic, s3, spaces, r2, keygen, bitbucket, github and gitlab providers, a download on another origin than the feed (scheme, host or port) — an absolute files[].url or packages.<arch>.path in latest*.yml, a GitLab release asset link, and the blockmaps and differential range requests derived from them — is requested without the credential headers from requestHeaders / addAuthHeader (headers such as Authorization, the same set that is removed on a cross-origin redirect) and without the feed URL's query string. Such a URL keeps its own query string, so pre-signed URLs work. With every provider, including custom ones, a URL that electron-updater resolves against the feed URL (such as a files[].url or a blockmap) gets the feed query only on the feed's origin; as on redirects, an http → https upgrade of the feed host on the default ports keeps the headers and the query. Downloads on the feed origin are unchanged, and the old blockmap from an app-set previousBlockmapBaseUrlOverride keeps the credentials on that origin. If your latest*.yml points downloads at another origin that needs these credentials, serve the files from the feed origin or use pre-signed URLs. The NSIS web-package differential download now uses the same per-download headers as other downloads. A custom provider that does not extend a built-in one must declare Provider.feedBaseUrl — its feed URL (the credential headers then only go to that origin) or null (the request headers go to every download URL) — when the download headers include a credential header: if it does not, downloadUpdate() fails with ERR_UPDATER_FEED_BASE_URL_NOT_DECLARED before any download request. The first download that loses the credential headers, and the first that does not get the feed query, each log a warning once per updater, naming the headers, the query parameters and the origins (never their values), with a link to the migration guide; ERR_UPDATER_FEED_BASE_URL_NOT_DECLARED links it too. New APIs: Provider.feedBaseUrl (undefined, not declared, by default), HttpExecutor.sensitiveHeaderNames, HttpExecutor.removeCrossOriginSensitiveHeaders and HttpExecutor.isCrossOrigin. #10270 ec9135d @mmaietta

  • Feat!: NSIS web-installer updates are rejected unless disableWebInstaller is false (the v27 grace period is removed; cached and install-on-next-launch web updates re-verify the web package), and the nsis-web installer verifies --package-file and versioned package downloads against its built-in SHA-512 hashes (opt out with nsisWeb.allowUnverifiedAppPackage). Set disableWebInstaller before the app is ready: a pending install-on-next-launch web update is checked against it at app ready #10264 c8ca1ac @mmaietta

Minor Changes

  • Feat(updater): optional files[].blockMapUrl in latest*.yml names a file's blockmap URL (e.g. a separately pre-signed one) instead of ${url}.blockmap with the file URL's query string. A relative value resolves like url (against the feed URL); an absolute URL is used as-is, with its own host and query string. It gets the feed query and credential headers only on the feed's origin. With a blockMapUrl, the old blockmap is not derived from the new file's URL: it comes from the local cache, else from previousBlockmapBaseUrlOverride, else that update is downloaded in full (which caches the new blockmap). The manifest signature covers blockMapUrl when present, as an extra field on the file record, so manifests without it canonicalize and verify exactly as before; an electron-updater without this change refuses a signed manifest that has one. electron-builder does not write it. The private GitHub and GitLab providers, which resolve files from the release assets, ignore it. #10270 ec9135d @mmaietta

Patch Changes

  • Fix: report accurate differential download progress deltas #10118 58e5d2e @OskarEichler
  • Feat!: a code-signed Windows build that writes app-update.yml (an nsis, nsis-web or electronUpdaterAware appx target with a publish configuration, including one inferred from a GitHub repository) now fails with an InvalidConfigurationError when its publisher name cannot be determined: any custom win.sign.sign hook without win.sign.publisherName (its publisher name is never derived from a certificate, not even one in the config — certificateFile, certificateSubjectName, certificateSha1, cscLink — or from WIN_CSC_LINK / CSC_LINK, because the hook may sign with another one), or a certificate without a Common Name (including a certificate-store subject, which no longer yields an undefined publisher name). Set win.sign.publisherName to the subject of the signing certificate (copy it from a binary your hook already signed), or set win.verifyUpdateCodeSignature: false only if your updates are not Authenticode-signed or you don't use electron-updater. Error and warning messages now name win.sign.publisherName instead of the removed win.publisherName. #10264 c8ca1ac @mmaietta
  • Fix(updater): pass the web installer package to verifyUpdateFile as packageFilePath when a pending web update is installed on next launch #10264 c8ca1ac @mmaietta
  • Fix: handle background download rejections from checkForUpdatesAndNotify #10113 c10345f @OskarEichler
  • Fix(updater): pass the NSIS install directory (installDirectory, /D=) as the last installer argument, after --package-file #10264 c8ca1ac @mmaietta
  • Chore: replace ESLint and Prettier with oxlint and oxfmt #10240 a578e53 @claude
  • Fix: reject traversal segments as update cache filenames #10127 e832c81 @OskarEichler
  • Fix(updater): the warning about disableWebInstaller set to false for a full-installer update is logged only when the app set it; for the default of an install made by an nsis-web installer an info line says that web-installer updates need disableWebInstaller = false after that update #10264 c8ca1ac @mmaietta
  • Feat!: the nsis-web installer verifies and installs its own copy of a local app package. A package passed via --package-file (electron-updater does this for updates) or found next to the installer is first copied into the installer's own temporary directory; the checksum is computed on that copy and that copy is what is extracted. With nsisWeb.allowUnverifiedAppPackage a package passed via --package-file is still copied, but not verified. The local package file is now left in place (the installer's copy is moved into the app's update cache instead), and the installation is aborted (exit code 2) if a --package-file package cannot be copied; a package found next to the installer that cannot be copied is ignored and the package is downloaded, as when its checksum doesn't match. electron-updater removes the package it passed via --package-file from its pending cache directory at startup once the app runs the version of that update (update-info.json records the version of a web installer update for this); the package of an update that is not installed yet, or whose install failed, is kept. #10264 c8ca1ac @mmaietta
Updated 1 dependency

ec9135d ec9135d ec9135d

  • builder-util-runtime@10.0.0-alpha.9

Don't miss a new electron-builder release

NewReleases is sending notifications on new releases.