feat(updater): robust PowerShell invocation for Windows code-signature verification#9764
Open
mmaietta wants to merge 11 commits into
Open
feat(updater): robust PowerShell invocation for Windows code-signature verification#9764mmaietta wants to merge 11 commits into
mmaietta wants to merge 11 commits into
Conversation
…Encoding = [Console]::OutputEncoding = [Text.Encoding]::UTF8` for windows signing verification via powershell
🦋 Changeset detectedLatest commit: fc65654 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
This PR updates how electron-updater invokes PowerShell to verify Windows Authenticode signatures, aiming to improve reliability on newer Windows Server versions and to ensure UTF-8 output handling without going through cmd.exe.
Changes:
- Refactor PowerShell invocation to use
shell: false+-EncodedCommand, and configure UTF-8 output inside PowerShell. - Adjust module-loading /
PSModulePathhandling intended to avoid autoload issues on newer Windows Server versions. - Add unit + Windows-only e2e tests (with a snapshot) covering invocation parameters, escaping, and key verification behaviors.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts |
Refactors preparePowerShellExec to use -EncodedCommand, sets shell: false, and moves encoding/module setup into the PowerShell script. |
test/src/updater/windowsExecutableCodeSignatureVerifierTest.ts |
Adds comprehensive unit tests (mocked) and Windows-only e2e tests (real PowerShell) for signature verification and command construction/escaping. |
test/snapshots/updater/windowsExecutableCodeSignatureVerifierTest.js.snap |
Adds snapshot for the PowerShell executable + args (including encoded command). |
.changeset/late-results-grab.md |
Declares a minor changeset for electron-updater reflecting the PowerShell invocation change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… not changing the snapshot (e.g. encodedcommand) every run
shell: false and -EncodedCommand for windows signing verification via powershell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #9688 —
Get-AuthenticodeSignaturefailures on Windows 10 / Electron 40 / Node 24 configurations.Summary
Core fix —
shell: false+-EncodedCommand: PowerShell is now invoked directly viaexecFileinstead of being chained throughcmd.exe. The command is passed as a Base64-encoded UTF-16LE string via-EncodedCommand, removing the cmd.exe invocation and thechcp 65001 >NUL &pipeline entirely.UTF-8 output encoding: Moved from the
chcp 65001shell command to$OutputEncoding = [Console]::OutputEncoding = [Text.Encoding]::UTF8configured inside the PowerShell script. Both variables must be set together forConvertTo-Jsonto emit UTF-8 when stdout is captured by Node (fixes Certificates with special characters are not accepted anymore since electron-updater v1.6.9 #8162 class of errors — non-ASCII characters in the update path).Module loading hardened:
Import-Moduleuses"$PSHOME\Modules\Microsoft.PowerShell.Security"(PowerShell's own trusted install directory) before$env:PSModulePathis cleared, so the correct module is loaded even on Windows Server 2025 where auto-loading requires PSModulePath at import time. PSModulePath is also deleted from the Node-sideenvoption as belt-and-suspenders.Progress-stream suppression:
$ProgressPreference = 'SilentlyContinue'is set first in the script so the "Preparing modules for first use." CLIXML record is never written to stderr, eliminating false-positive error detection on first-run environments.Bug fix — double-reject in
handleError: The previousif (error) { reject() } if (stderr) { reject() }pattern could settle the Promise twice when both fields were set. Corrected toelse if.Typo fix:
normlaizedUpdateFilePath→normalizedUpdateFilePath.Reduced cyclomatic complexity: Extracted three private helpers to flatten
verifySignature(CC 6 → 3):checkLiteralPath— validatesdata.Pathagainst the expected update path and callsreject()directly on mismatch (removes the spurious ConvertTo-Json probe on path-mismatch failures).matchPublisher— DN matching loop.evaluateSignatureResult— parses the PS JSON output and coordinates the LiteralPath + publisher checks.Path injection comment trimmed: Multi-line example block replaced with a 2-line explanation (WHY only — PowerShell single-quoted strings make
$,`, and\literal; only'needs escaping).Test —
vi.importActualmoved tobeforeAll: In the e2e describe block, the expensivevi.importActualcalls for realchild_processandosimplementations are obtained once inbeforeAllrather than re-fetched before every test inbeforeEach.Test coverage (unit, platform-agnostic): 46 tests pass, up from 41. New cases cover:
"") rejects via the catch path (JSON.parse throws).$in path is passed verbatim inside the single-quoted PS string.Test coverage (e2e, Windows-only
describe.ifWindows): 4 new real-PowerShell tests validate that directory names containing&,%VAR%,$, and backtick characters — which were dangerous under the oldcmd.exe-based invocation — now complete without crash or spurious rejection.Changed Files
packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.tsshell: false,-EncodedCommand, helper extraction, bug fixes, comment cleanuptest/src/updater/windowsExecutableCodeSignatureVerifierTest.tsvi.importActualmoved tobeforeAlltest/snapshots/updater/windowsExecutableCodeSignatureVerifierTest.js.snap