Found while documenting the Sign settings for #189.
PowerShellBuild/build.properties.ps1 documents the setting as applying to Store and Thumbprint:
When true and using the Store or Thumbprint sources, skip the certificate validity check that ensures the certificate is not expired and has a private key. This is not recommended for production use but can be useful in CI environments where certificates are frequently renewed and updated.
Get-PSBuildCertificate implements the opposite. The switch is only consulted for EnvVar and PfxFile:
# Get-PSBuildCertificate.ps1:180
if ($cert -and -not $SkipValidation -and ($resolvedSource -eq "EnvVar" -or $resolvedSource -eq "PfxFile")) {
For Store and Thumbprint the same two checks run unconditionally, inside the selection filter, where the switch cannot reach them:
# Store, line 133
Get-ChildItem -Path $CertStoreLocation -CodeSigningCert |
Where-Object { $_.HasPrivateKey -and $_.NotAfter -gt (Get-Date) } |
Select-Object -First 1
# Thumbprint, lines 147-152
Where-Object {
($_.Thumbprint -replace "\s", "") -ieq $normalizedThumbprint -and
$_.HasPrivateKey -and
$_.NotAfter -gt (Get-Date)
}
Why it matters
The setting exists for the CI case the comment names — a certificate that has just expired or is being rotated. A consumer who sets $PSBPreference.Sign.SkipCertificateValidation = $true with a store certificate does not get a bypass. The certificate is filtered out before validation is ever considered, and the build fails with NoCertificateFound, which points at a missing certificate rather than at the expiry that actually caused it. The documented escape hatch does not work for the source it is documented for.
Note the asymmetry in how the two paths report failure, too: EnvVar and PfxFile throw the specific CertificateExpired / CertificateMissingPrivateKey messages, while Store and Thumbprint silently drop the certificate and fall through to the generic one.
Which is wrong, the comment or the code?
That is the decision this issue needs, and it is a behavior call rather than a documentation one:
- Fix the code — move the
HasPrivateKey / NotAfter checks out of the Where-Object filters for Store and Thumbprint and into the shared validation block, so SkipValidation governs all four sources uniformly. This makes the setting do what it says, and as a side effect the two paths would start reporting why a certificate was rejected. It is a behavior change: a build that currently skips an expired store certificate and picks a valid one further down the list would instead select the expired one when validation is skipped.
- Fix the comment — narrow it to
EnvVar and PfxFile, and say plainly that Store and Thumbprint always filter on validity with no way to opt out.
I lean toward fixing the code, because the CI scenario the comment describes is real and currently unserved, but it is a 1.0.0 behavior change and should be a maintainer decision.
Scope note
build.properties.ps1 was deliberately left unchanged in #190. That PR documents the implemented behavior in the README rather than the commented behavior, so the README is accurate today whichever way this issue is resolved.
Related: #178, another setting that read one name and bound nothing.
Found while documenting the
Signsettings for #189.PowerShellBuild/build.properties.ps1documents the setting as applying toStoreandThumbprint:Get-PSBuildCertificateimplements the opposite. The switch is only consulted forEnvVarandPfxFile:For
StoreandThumbprintthe same two checks run unconditionally, inside the selection filter, where the switch cannot reach them:Why it matters
The setting exists for the CI case the comment names — a certificate that has just expired or is being rotated. A consumer who sets
$PSBPreference.Sign.SkipCertificateValidation = $truewith a store certificate does not get a bypass. The certificate is filtered out before validation is ever considered, and the build fails withNoCertificateFound, which points at a missing certificate rather than at the expiry that actually caused it. The documented escape hatch does not work for the source it is documented for.Note the asymmetry in how the two paths report failure, too:
EnvVarandPfxFilethrow the specificCertificateExpired/CertificateMissingPrivateKeymessages, whileStoreandThumbprintsilently drop the certificate and fall through to the generic one.Which is wrong, the comment or the code?
That is the decision this issue needs, and it is a behavior call rather than a documentation one:
HasPrivateKey/NotAfterchecks out of theWhere-Objectfilters forStoreandThumbprintand into the shared validation block, soSkipValidationgoverns all four sources uniformly. This makes the setting do what it says, and as a side effect the two paths would start reporting why a certificate was rejected. It is a behavior change: a build that currently skips an expired store certificate and picks a valid one further down the list would instead select the expired one when validation is skipped.EnvVarandPfxFile, and say plainly thatStoreandThumbprintalways filter on validity with no way to opt out.I lean toward fixing the code, because the CI scenario the comment describes is real and currently unserved, but it is a 1.0.0 behavior change and should be a maintainer decision.
Scope note
build.properties.ps1was deliberately left unchanged in #190. That PR documents the implemented behavior in the README rather than the commented behavior, so the README is accurate today whichever way this issue is resolved.Related: #178, another setting that read one name and bound nothing.