ci(windows): tolerate untrusted root in signature verification for test cert

signtool verify /pa exits non-zero when the certificate chain terminates in
an untrusted root, which is always the case for the SignPath self-signed test
certificate. Add an -AllowUntrustedRoot switch to verify-authenticode.ps1 that
accepts a signed-but-untrusted-root result (while still failing on unsigned or
otherwise invalid files), and pass it from the workflow during test-signing.

Remove the switch once signing-policy-slug moves to release-signing with a
production CA-issued certificate, so release builds enforce a fully trusted chain.
This commit is contained in:
SoftFever
2026-05-30 01:52:51 +08:00
parent ebdfa74ce8
commit 48acf4f13b
2 changed files with 39 additions and 5 deletions

View File

@@ -323,7 +323,10 @@ jobs:
- name: Verify SignPath Windows portable signatures
if: github.repository == 'OrcaSlicer/OrcaSlicer' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && runner.os == 'Windows' && !vars.SELF_HOSTED
shell: pwsh
run: ./scripts/verify-authenticode.ps1 -ArtifactDirectory '${{ github.workspace }}/build/signpath/windows-portable'
# -AllowUntrustedRoot is required while signing with the SignPath test
# certificate (self-signed). Remove it once signing-policy-slug switches
# to release-signing with a production CA-issued certificate.
run: ./scripts/verify-authenticode.ps1 -ArtifactDirectory '${{ github.workspace }}/build/signpath/windows-portable' -AllowUntrustedRoot
- name: Replace Windows portable bundle with signed output
if: github.repository == 'OrcaSlicer/OrcaSlicer' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && runner.os == 'Windows' && !vars.SELF_HOSTED

View File

@@ -9,7 +9,13 @@ param(
"OrcaSlicer.dll"
),
[string]$SignToolPath
[string]$SignToolPath,
# Accept signatures whose certificate chain terminates in an untrusted root.
# Required for the SignPath test certificate (self-signed). Do NOT pass this
# once a production CA-issued certificate is in use, so release builds enforce
# a fully trusted chain.
[switch]$AllowUntrustedRoot
)
$ErrorActionPreference = "Stop"
@@ -64,10 +70,35 @@ foreach ($relativePath in $Files) {
}
Write-Host "Verifying $relativePath"
& $signtool verify /pa /all /tw /v $filePath
if ($LASTEXITCODE -ne 0) {
throw "SignTool verification failed for '$relativePath' with exit code $LASTEXITCODE."
# Capture signtool output without letting native stderr (redirected via 2>&1)
# raise a terminating NativeCommandError under $ErrorActionPreference = 'Stop'.
$previousErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = "Continue"
try {
$output = & $signtool verify /pa /all /tw /v $filePath 2>&1
$exitCode = $LASTEXITCODE
}
finally {
$ErrorActionPreference = $previousErrorActionPreference
}
$output | ForEach-Object { Write-Host $_ }
if ($exitCode -eq 0) {
continue
}
# signtool wraps the message across lines, so normalize whitespace before matching.
$normalizedOutput = (($output | Out-String) -replace "\s+", " ")
$isUntrustedRoot = $normalizedOutput -match "terminated in a root certificate which is not trusted by the trust provider"
if ($AllowUntrustedRoot -and $isUntrustedRoot) {
Write-Host " Accepted: '$relativePath' is signed but its certificate chains to an untrusted root (expected for the SignPath test certificate)."
continue
}
throw "SignTool verification failed for '$relativePath' with exit code $exitCode."
}
Write-Host "Authenticode verification passed."