Major Changes
-
Feat(win)!: a missing
publisherNamefails Windows update signature verification closed.#10380674e18d—electron-updater,builder-util-runtime- electron-updater: an NSIS update is rejected with
ERR_UPDATER_INVALID_SIGNATUREwhenapp-update.yml(ordev-app-update.yml/ theupdateConfigPathfile) has nopublisherName. A customverifyUpdateFileAuthenticodeSignature/verifyUpdateCodeSignatureis never called without apublisherName. The only opt-out isverifyUpdateCodeSignature: falseinapp-update.yml, which electron-builder writes forwin.verifyUpdateCodeSignature: false; verification is then skipped with one warning per updater. An app with no update config file at all (noapp-update.yml/dev-app-update.yml, e.g. one that only usessetFeedURL) is not verified: its feed is configured by the developer. - app-builder-lib: a Windows build that writes
app-update.yml(nsis,nsis-weborelectronUpdaterAwareappxwith a publish configuration of any provider, including one inferred from a GitHubrepository) fails withInvalidConfigurationErrorwhilewin.verifyUpdateCodeSignatureis enabled and nopublisherNameresolves:win.sign: false/null, no code signing certificate, orwin.sign.publisherName: null, which is not an opt-out. Sign the build, setwin.sign.publisherName(e.g.win.sign: { type: "signtool", publisherName: [...] }when signing outside electron-builder), or setwin.verifyUpdateCodeSignature: false, which writesverifyUpdateCodeSignature: false(and nopublisherName) intoapp-update.yml. ApublisherNamein thepublishconfiguration must be a distinguished name too, andverifyUpdateCodeSignaturemust not be set there. - builder-util-runtime:
PublishConfigurationhas the private, Windows-onlyverifyUpdateCodeSignaturefield. - electron-builder:
migrate-schemaprints an advisory forwin.sign: false/nullorwin.sign.publisherName: nullwithoutwin.verifyUpdateCodeSignature: false.
- electron-updater: an NSIS update is rejected with
-
Feat(win)!:
matchPublisherNamematches only publisher names that are a distinguished name (DN), every attribute of which must equal the signer's; a bare name never matches the signer's Common Name any more, and itsloggerparameter is removed. New exportisValidPublisherNameDntells whether a publisher name is a DN. See https://www.electron.build/docs/migration/v27-build-changes#windows-publishername-must-be-a-distinguished-name#10380674e18d—builder-util-runtime -
Feat(updater)!: Windows update signature verification fails closed — electron-updater installs an NSIS update only when PowerShell (
Get-AuthenticodeSignature) verifies it: an update it cannot verify (PowerShell cannot be started or run, times out, or prints unreadable output) is rejected withERR_UPDATER_SIGNATURE_UNVERIFIABLE, and a Windows catalog signature is rejected as invalid unless the app opts in with the newNsisUpdater.allowCatalogSignature(defaultfalse; whentrue, a valid catalog signature is accepted with a warning only when its signer matchespublisherName). A release can allow it instead with the newwin.allowCatalogSignaturebuild option (defaultfalse), which writesallowCatalogSignature: trueinto thelatest.ymlof thensisandnsis-webtargets; electron-updater honors it only when that manifest's signature was verified against a trusted key (updateManifestPublicKey) and ignores it with a warning otherwise. The manifest signature covers it as an extraallowCatalogSignature:trueline of theEBUM1payload only when it istrue, so manifests without it canonicalize and verify exactly as before, and changing it for a published release means re-signing or republishinglatest.yml; a signed manifest with a non-booleanallowCatalogSignatureis rejected. electron-updater 7.0.0-alpha.8 to alpha.11 installs with an update key configured reject a signed manifest that sets it (ERR_UPDATER_MANIFEST_SIGNATURE_INVALID), the same way alpha.8 treats a signedfiles[].blockMapUrl.UpdateInfoAndProvidergainsmanifestSignatureVerified, andBaseUpdater.verifyInstallerSignatureOnLaunchreceives the update info the cached installer was matched against. PowerShell is started by absolute path, the installer path is passed in an environment variable, and non-ASCII output is escaped instead of setting a console encoding, so verification works under PowerShell Constrained Language Mode (fixing 7.0.0-alpha.8 to alpha.10). The build-time installer check uses the same invocation. builder-util-runtime addsprepareAuthenticodeSignatureExecandPOWERSHELL_ASCII_ESCAPE_FUNCTION. Migration: where PowerShell may be blocked (AppLocker / WDAC), assign a nativeverifyUpdateFileAuthenticodeSignaturein your first electron-updater 7 release — see https://www.electron.build/docs/migration/v27-runtime-changes#windows-update-signature-verification-fails-closed#104168366dc6—electron-updater,builder-util-runtime -
Feat(win)!: the default Authenticode verification of NSIS updates accepts an update only when a
publisherNameentry in distinguished name (DN) format (e.g."CN=My Company, O=My Company, C=US") matches its signer: a bare name, which used to match the signer's Common Name with a warning, never matches. Such an entry (from anapp-update.ymlwritten by electron-builder before v27, adev-app-update.ymlor a direct call ofverifyUpdateFileAuthenticodeSignature) is warned about once per updater, and theERR_UPDATER_INVALID_SIGNATUREfailure names it. Build the app with electron-builder v27, which writes a DN (CN=<common name>of the certificate unlesspublisherNameis configured). See https://www.electron.build/docs/migration/v27-build-changes#windows-publishername-must-be-a-distinguished-name#10380674e18d -
Refactor(win)!: remove the
escapePowerShellSingleQuotesexport, which only shipped in 10.0.0-alpha.11; the Authenticode check passes the file path to PowerShell in an environment variable (prepareAuthenticodeSignatureExec), so no path is quoted into a PowerShell script.#10453ed05bd0—builder-util-runtime
Minor Changes
-
Feat: warn on silently skipped update signature verification and validate
publisherNameagainst the signing certificate at build time#10056331afdd— updated in#10380Two guards around Windows update signature verification:
- electron-updater: when
app-update.ymlexists but contains nopublisherName, the updater used to skip signature verification (including customverifyUpdateCodeSignaturehooks) completely silently. It now logs a warning explaining that verification was skipped, how to fix it (sign the build sopublisherNameis derived automatically, or setwin.publisherNameexplicitly), and that this fail-open behavior is deprecated. Since v27 (electron-updater 7), a missingpublisherNamein an existingapp-update.ymlis a verification failure (fail-closed) instead, unless the file hasverifyUpdateCodeSignature: false. The no-app-update.ymlpath (unpackaged/dev mode) stays silent. - app-builder-lib: when
publisherNameis explicitly configured and the subject of the local code signing certificate is known, the build now fails with a clear error if none of the configured names match the certificate (same DN-subset/CN matching semantics as the updater's verifier; any one of multiple configured names matching passes, so certificate-rotation setups keep working). This catches signing with the wrong certificate at build time instead of at update time. The check is skipped whenever the actual signing certificate's subject is not genuinely known (customsignhooks, Azure Trusted Signing, PKCS#11 without an extractable certificate, x509 files without a CN), andpublisherName: nullremains a pure opt-out.
- electron-updater: when
-
Feat(runtime):
HttpExecutor.addRedirectHandlersis public, so that requests made outside the executor (electron-updater's differential downloads) follow redirects with the same rules: credential headers are dropped on another origin, and the executor's redirect limit applies#104192d97c85—builder-util-runtime -
Feat(win): export
windowsPowerShellPath(), which returns the absolute path of the in-box Windows PowerShell (%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe) for runtime use such as electron-updater, and throws whenSystemRootis not a drive-absolute path.preparePowerShellExecandprepareAuthenticodeSignatureExectake an optional PowerShell path, used instead ofwindowsPowerShellPath()when given.#10453ed05bd0—builder-util-runtime
Patch Changes
- Fix(updater): differential downloads made with single range requests no longer send credential headers such as
Authorizationto a redirect target on another origin, which made pre-signed S3 or R2 URLs reject the range requests and forced a full download#104137167926 - Refactor(win): export the Windows Authenticode helpers electron-updater verifies update signatures with (
preparePowerShellExec,parseAuthenticodeSignatureOutput,matchPublisherName), moved from electron-updater so electron-builder can check signed installers with the same code#1037860e3708—builder-util-runtime· updated in#10416 - Refactor(win): verify update signatures with the Authenticode helpers moved to builder-util-runtime
#1037860e3708— updated in#10416 - Docs: split the v27 breaking-changes page into config, build, runtime and developer pages, point the migration links in build and updater messages at the page each change moved to, and add links to the v27 messages that had none
#10421b5e144d - Start system tools by absolute path instead of looking them up on
PATH: Windows PowerShell from%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe(for Windows code signing, package-manager commands andcreate-self-signed-cert), PowerShell 7 from%ProgramFiles%\PowerShell\7\pwsh.exeon Windows and from the install location of Microsoft's package on macOS and Linux,prlctlfrom the Parallels Desktop install location, and the host Wine (toolsets.wine: "system", the default) from its fixed install locations.SystemRootandProgramFilesmust be drive-absolute paths.#10422a7f005c—builder-util-runtime - Electron-builder starts the host programs it uses only from an absolute path, never by looking up a name on
PATH: PowerShell, Wine, Mono (Squirrel.Windows on macOS and Linux),prlctl,productbuild,pkgbuild,codesign,hdiutil,tiffutil,sips,actool,zip,notarytool(passed to@electron/notarizeasnotarytoolPath, located with/usr/bin/xcrunby default),lzip,snapcraft,flatpakandflatpak-builder. Each comes from its default install locations or from the newtoolsets.executablesmap, whose entries arefile://URIs, or lists of them, that replace the defaults for that program. Child processes started without an explicit environment get no credential variables on Windows either, andsnapcraft uploadgets the store credentials but no other secret. The NSIS installer startstasklistandtaskkillfrom$SYSDIR(and passes the force flag in per-machine mode), the AppImage launcher runs the dialog tool it checked by its absolute path, and electron-updater on macOS starts/usr/sbin/sysctland/usr/bin/uname.#10430b98e1f2 - Fix(updater): every request of a differential download (single-range, multi-range and reading the embedded block map) follows redirects through
ElectronHttpExecutor.addRedirectHandlers: credential headers such asAuthorization,PRIVATE-TOKEN,X-Api-KeyandCookieare sent to a redirect target only on the same origin, a single-range download requests its remaining ranges from the redirect target while each multi-range request starts at the update URL, and at most 10 redirects are followed per request, as for everyElectronHttpExecutorrequest#104192d97c85 - Fix(runtime):
HttpExecutor.prepareRedirectUrlOptionsleaves outhost, so a redirected request goes to the redirect target even when the original request sethost(ElectronHttpExecutor sets it from aHostheader)#104192d97c85—builder-util-runtime - Fix: escaped characters in a Windows
publisherNamedistinguished name are decoded correctly. Before, a hex pair was decoded as a single Latin-1 character (Caf\C3\A9becameCaféinstead ofCafé), and a\+or\escape followed by a hex digit was read as a hex pair (Acme\+Boltlost theB), so such a publisher name never matched the signing certificate and electron-updater rejected the update#104346393d7a—builder-util-runtime - Fix(updater): settle a cancelled differential download with a
CancellationErrorinstead of hanging or falling back to a full download, and log a throwingdownload-progresslistener instead of letting it break the download or keep progress from the other listeners#103567efb3e6 - Fix: secrets in logs and error messages (passwords, tokens and keys in redacted command lines, environments and request options) are shown as a fingerprint keyed with a random secret of the process, derived with scrypt: the same value has the same fingerprint within a run, but a fingerprint cannot be checked against guessed values offline. A value whose fingerprint cannot be computed is shown as
<redacted>.#10441955cd00—electron-updater,builder-util-runtime - Fix: Fall back to Latin-1 when a hex escape in a distinguished name is not valid UTF-8
#104465028cb3—builder-util-runtime - Fix: reject update download redirects to non-HTTP(S) URLs instead of throwing an uncaught exception
#10448f68074d - Fix(updater): the
ERR_UPDATER_INVALID_SIGNATUREerror for anapp-update.ymlwithoutpublisherNamesays how to configure one (sign the build or setwin.sign.publisherName) and thatwin.verifyUpdateCodeSignature: falseis the opt-out, with a link to the migration guide.#10453ed05bd0