Private/Get-OSDStageBuiltInSignature.ps1

function Get-OSDStageExpectedPublisher {
    [CmdletBinding()]
    param([Parameter(Mandatory)][string]$Id)

    # Expected certificate organization. No thumbprint pinning: vendor
    # signing certificates rotate. Treat a changed publisher as a release
    # blocker requiring review, not a reason to silently trust a new one.
    switch ($Id) {
        'Microsoft365Apps'         { 'Microsoft Corporation'; break }
        'MicrosoftTeams'           { 'Microsoft Corporation'; break }
        'VisualStudioCode'         { 'Microsoft Corporation'; break }
        'VisualCRedist'          { 'Microsoft Corporation'; break }
        'DotNetRuntime'            { 'Microsoft Corporation'; break }
        'GoogleChromeEnterprise'   { 'Google LLC'; break }
        'CiscoWebex'               { 'Cisco Systems, Inc.'; break }
        'ZoomWorkplace'            { 'Zoom Communications, Inc.'; break }
        'MozillaFirefoxEnterprise' { 'Mozilla Corporation'; break }
        default                    { $null }
    }
}

function Test-OSDStageExpectedPublisher {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$Id,
        [string]$SignerSubject
    )

    $expected = Get-OSDStageExpectedPublisher -Id $Id
    if (-not $expected -or [string]::IsNullOrWhiteSpace($SignerSubject)) { return $false }

    # Extract the O= organization attribute, accepting quoted commas in an
    # RFC 2253-style subject such as Cisco Systems, Inc. Other attributes
    # including OU and CN do NOT grant publisher approval.
    $match = [regex]::Match($SignerSubject, '(?:^|,\s*)O=(?:"(?<quoted>(?:[^"]|"")*)"|(?<plain>[^,]+))(?=,|$)')
    if (-not $match.Success) { return $false }
    $org = if ($match.Groups['quoted'].Success) {
        $match.Groups['quoted'].Value.Replace('""','"')
    } else { $match.Groups['plain'].Value.Trim() }
    return [string]::Equals($org,$expected,[StringComparison]::OrdinalIgnoreCase)
}

function Assert-OSDStageBuiltInSignature {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$Id,
        [Parameter(Mandatory)][string]$FilePath
    )

    $signature = Get-OSDStageBuiltInSignature -Id $Id -FilePath $FilePath -CheckPublisher
    if ($signature.Status -ne 'Valid') {
        throw "Built-in '$Id' was rejected: signature status '$($signature.Status)' for '$FilePath'. Expected publisher: $(Get-OSDStageExpectedPublisher -Id $Id). Actual signer: $($signature.Signer)."
    }
    return $signature
}

function Get-OSDStageBuiltInSignature {
    <#
    .SYNOPSIS
    Inspects a cached built-in package's Authenticode signature without changing it.
    .NOTES
    Windows trust evaluation is environment- and time-dependent. A valid signature
    is not a guarantee of a current package or malware-free content. Windows may
    contact a revocation service when checking certificate trust.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$Id,
        [string]$CacheEntryPath,
        [string]$FilePath,
        [switch]$CheckPublisher
    )

    if ($Id -eq '7Zip') {
        return [pscustomobject]@{ Status='Not assessed'; Scope='Release SHA-256 (checked separately)'; File=$null; Signer=$null; Detail='7Zip uses the official release digest, not Authenticode publisher validation.' }
    }

    $fixedFile = switch ($Id) {
        'Microsoft365Apps' { 'setup.exe' }
        'MicrosoftTeams' { 'teamsbootstrapper.exe' }
        default { $null }
    }
    $extension = switch ($Id) {
        { $_ -in @('Microsoft365Apps','MicrosoftTeams','VisualStudioCode','VisualCRedist','DotNetRuntime') } { '.exe' }
        { $_ -in @('GoogleChromeEnterprise','CiscoWebex','ZoomWorkplace','MozillaFirefoxEnterprise','CMTraceOpen') } { '.msi' }
        default { $null }
    }
    if (-not $extension) {
        return [pscustomobject]@{Status='Not assessed';Scope='ZIP / unsupported type';File=$null;Signer=$null;Detail='Authenticode is not checked for this cache format.'}
    }
    $scope = if ($Id -eq 'MicrosoftTeams') { 'Bootstrapper EXE only (MSIX not checked)' }
        elseif ($Id -eq 'Microsoft365Apps') { 'Office setup.exe only (Office data not checked)' }
        elseif ($extension -eq '.msi') { 'MSI package' } else { 'EXE file' }
    if (-not $FilePath -and -not $CacheEntryPath) { throw 'Specify -CacheEntryPath or -FilePath.' }
    $path = $null
    try {
        $path = if ($FilePath) { $FilePath } elseif ($fixedFile) { Join-Path $CacheEntryPath $fixedFile }
            else { Resolve-OSDStageBuiltInPayloadPath -Root $CacheEntryPath -ExpectedExtension $extension }
    }
    catch {
        return [pscustomobject]@{Status='File missing';Scope=$scope;File=$null;Signer=$null;Detail=$_.Exception.Message}
    }
    if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
        return [pscustomobject]@{Status='File missing';Scope=$scope;File=$path;Signer=$null;Detail='Required signature target is missing.'}
    }
    if (Test-OSDStageWinPE) {
        return [pscustomobject]@{
            Status='Unavailable in WinPE';Scope=$scope;File=$path;Signer=$null
            Detail='Full Windows Authenticode inspection was not attempted in WinPE.'
        }
    }

    try {
        # Use the installed Windows trust provider in read-only mode.
        $signature = Get-AuthenticodeSignature -LiteralPath $path -ErrorAction Stop
        $status = [string]$signature.Status
        if (-not $status) { $status = 'UnknownError' }
        $signer = if ($signature.SignerCertificate) {
            [string]$signature.SignerCertificate.Subject
        } else { $null }
        $expectedPublisher = Get-OSDStageExpectedPublisher -Id $Id
        $publisherMatches = if ($signer -and $expectedPublisher) {
            Test-OSDStageExpectedPublisher -Id $Id -SignerSubject $signer
        } else { $false }
        if ($CheckPublisher -and $status -eq 'Valid' -and $expectedPublisher -and -not $publisherMatches) {
            $status = 'PublisherMismatch'
        }
        return [pscustomobject]@{
            Status=$status
            Scope=$scope
            File=$path
            Signer=$signer
            ExpectedPublisher=$expectedPublisher
            PublisherMatches=$publisherMatches
            Detail=if ($status -eq 'PublisherMismatch') {
                "The valid signature was not issued to expected publisher '$expectedPublisher'."
            } elseif ($signature.StatusMessage) {
                [string]$signature.StatusMessage
            } else { $status }
        }
    }
    catch {
        Write-Verbose "Authenticode inspection unavailable for '$path': $($_.Exception.Message)"
        return [pscustomobject]@{
            Status='Check failed';Scope=$scope;File=$path;Signer=$null
            Detail=$_.Exception.Message
        }
    }
}