Files
hermes-agent/apps/desktop/scripts/verify-signed-payloads.ps1
ethernet 276174db7e fix(signing): verify embedded signatures behind Windows catalogs
PowerShell selects the Microsoft catalog signature for some payload DLLs.
That hides the valid Nous signature and rejects the signed payload cache.

For catalog matches, verify the primary embedded signature with signtool.
Require a trusted timestamp and the expected embedded publisher. Keep the
existing content binding and reject catalog-only trust.

The native regression rejects corrupt certificates and missing timestamps.
All 36 focused tests pass. Real Azure signing and duplicate restoration
pass with signer calls forbidden on the warm cache path. Full release
acceptance remains pending.
2026-09-08 01:31:02 -04:00

36 lines
1.6 KiB
PowerShell

param(
[Parameter(Mandatory = $true)][string]$Manifest,
[string]$SignTool = ''
)
$ErrorActionPreference = 'Stop'
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
$items = Get-Content -Raw -LiteralPath $Manifest | ConvertFrom-Json
$results = @(
foreach ($item in $items) {
$signature = Get-AuthenticodeSignature -LiteralPath $item.path
$valid = $signature.Status -eq 'Valid' -and
$signature.SignatureType -eq 'Authenticode' -and
$null -ne $signature.TimeStamperCertificate -and
$signature.SignerCertificate.Subject -eq $item.publisher
if ($signature.SignatureType -eq 'Catalog' -and $SignTool) {
# Catalog lookup hides a replacement embedded signature. Verify index 0,
# without /a, so catalog trust cannot approve corrupt or unsigned bytes.
$exitCode = & {
# PowerShell 5 turns redirected native stderr into a terminating error.
$ErrorActionPreference = 'Continue'
$global:LASTEXITCODE = $null
& $SignTool verify /pa /tw /ds 0 $item.path *> $null
$global:LASTEXITCODE
}
$valid = $false
if ($exitCode -eq 0) {
$certificate = [Security.Cryptography.X509Certificates.X509Certificate]::CreateFromSignedFile($item.path)
try { $valid = $certificate.Subject -eq $item.publisher }
finally { $certificate.Dispose() }
}
}
[PSCustomObject]@{ path = $item.path; valid = [bool]$valid }
}
)
ConvertTo-Json -InputObject $results -Compress