Keep elevate.exe signed through the NSIS rebuild

electron-builder's CopyElevateHelper re-copies a pristine elevate.exe
from its download cache on every NSIS pack, which clobbered the round-1
SignPath signature in v1.4.129-rc.4 (caught by the evidence gate).
Overwrite the cached copy with the signed one before the rebuild so the
clobber becomes a no-op, and make the evidence gate verify
resources\elevate.exe in every release regardless of whether staging
listed it (the persisted cache can carry an already-signed copy).
This commit is contained in:
Jinwoo Hong
2026-07-09 00:53:07 -04:00
parent 898d4b5e66
commit 18bbc44dd7
2 changed files with 51 additions and 2 deletions
+50 -2
View File
@@ -1132,6 +1132,45 @@ jobs:
throw "Signed inner artifact did not round-trip cleanly ($($failures.Count) failures)."
}
# Why this step exists: electron-builder's CopyElevateHelper re-copies a
# pristine elevate.exe from its download cache over resources\elevate.exe
# on EVERY nsis pack — including the --prepackaged rebuild below — which
# clobbered the SignPath signature in v1.4.129-rc.4. There is no supported
# way to disable just the copy, so we overwrite the cache's copy with our
# signed one (identical bytes plus signature) so the clobber becomes a
# no-op. Known quirk: the cache persists across releases via actions/cache,
# so later runs may see elevate.exe as already signed and skip staging it —
# that is fine (the signature is timestamped) and the evidence gate checks
# elevate.exe in the shipped installer unconditionally. If this ever causes
# trouble, delete this step; the only effect is elevate.exe shipping
# unsigned again, which the evidence gate will flag.
- name: Replace cached elevate.exe with the signed copy
id: sign-elevate-cache
if: matrix.platform == 'win' && steps.restore-signed-inner.outcome == 'success'
continue-on-error: true
shell: pwsh
run: |
$signed = 'dist/win-unpacked/resources/elevate.exe'
if (-not (Test-Path $signed)) {
Write-Host '::warning::No elevate.exe in win-unpacked resources; nothing to protect from the rebuild clobber.'
exit 0
}
$signature = Get-AuthenticodeSignature -FilePath $signed
$subject = if ($null -eq $signature.SignerCertificate) { '<none>' } else { $signature.SignerCertificate.Subject }
if ($signature.Status -ne 'Valid' -or $subject -notlike '*CN=SignPath Foundation*') {
Write-Host "::warning::win-unpacked elevate.exe is not SignPath-signed ($($signature.Status), $subject); skipping cache swap."
exit 0
}
$cached = @(Get-ChildItem "$env:LOCALAPPDATA\electron-builder\Cache\nsis" -Recurse -Filter elevate.exe -ErrorAction SilentlyContinue)
if ($cached.Count -eq 0) {
Write-Host '::warning::No cached elevate.exe found (electron-builder cache layout changed?); the rebuild will pack the unsigned copy and the evidence gate will flag it.'
exit 0
}
foreach ($file in $cached) {
Copy-Item -Path $signed -Destination $file.FullName -Force
Write-Host "Replaced $($file.FullName) with the SignPath-signed copy."
}
- name: Rebuild NSIS installer from signed unpacked app
id: rebuild-nsis-signed
if: matrix.platform == 'win' && steps.restore-signed-inner.outcome == 'success'
@@ -1325,7 +1364,16 @@ jobs:
& $7za x 'dist/orca-windows-setup.exe' '-oinner-evidence-extract' -y | Out-Null
$root = Resolve-Path 'inner-evidence-extract'
foreach ($relative in Get-Content 'inner-signing-list.txt') {
# Why elevate.exe is always appended: staging skips already-signed
# files, and the persisted electron-builder cache can carry a
# previously signed elevate.exe — so it may be absent from the list
# in some runs, yet it is the file most at risk of losing its
# signature in the NSIS rebuild. Verify it in every release.
$targets = @(Get-Content 'inner-signing-list.txt')
if ($targets -notcontains 'resources\elevate.exe') {
$targets += 'resources\elevate.exe'
}
foreach ($relative in $targets) {
$path = Join-Path $root $relative
if (-not (Test-Path $path)) {
$failures.Add("missing from installer payload: $relative")
@@ -1348,7 +1396,7 @@ jobs:
if ($required) { throw $message }
Write-Host "::warning::$message Fail-open until ORCA_WINDOWS_INNER_SIGNATURE_REQUIRED is 'true'."
} else {
Write-Host "All $((Get-Content 'inner-signing-list.txt').Count) inner binaries in the shipped installer are signed by SignPath Foundation."
Write-Host "All $($targets.Count) inner binaries in the shipped installer are signed by SignPath Foundation."
}
} catch {
if ($required) { throw }
@@ -254,6 +254,7 @@ describe('Electron runtime package contract', () => {
'Notify Slack that inner-binary signing is waiting for approval',
'Download signed inner binaries from SignPath',
'Restore signed inner binaries into unpacked app',
'Replace cached elevate.exe with the signed copy',
'Rebuild NSIS installer from signed unpacked app'
]
for (const stepName of innerChainStepNames) {