From c974f1615e5bd31a41761b3ca2e7fc64b2f9c00e Mon Sep 17 00:00:00 2001 From: Chuy Zarate Date: Tue, 21 Apr 2026 14:53:42 -0600 Subject: [PATCH] Add catalog signing for .js files and direct signing for .cab files The VS signing scan requires every signable file to carry its own signature. The Mono workload packs contain 480 unsigned files: - 198 .js files (browser-wasm runtime scripts) - 282 .cab files (WiX cabinet archives inside MSIs) For .js files: keep CertificateName=None (same as dotnet/emsdk#1671) because these are customer-modifiable runtime files. Instead, generate a .cat catalog file covering all .js files, signed via FileExtensionSignInfo for .cat. The GenerateCatalogFiles target runs after AddMonoRuntimeFiles on Windows browser-wasm builds. For .cab files: add FileExtensionSignInfo with Microsoft400 so the Arcade SDK SignTool signs them directly. Both Microsoft400 entries are auto-replaced by MicrosoftDotNet500 since UseDotNetCertificate=true. Tracking: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2911494 --- eng/Signing.props | 8 +- eng/generate-catalog.ps1 | 93 +++++++++++++++++++ ...Microsoft.NETCore.App.Runtime.Mono.sfxproj | 25 +++++ 3 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 eng/generate-catalog.ps1 diff --git a/eng/Signing.props b/eng/Signing.props index c3fd63545484ff..56a3574f0abda2 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -49,9 +49,13 @@ - - + + + diff --git a/eng/generate-catalog.ps1 b/eng/generate-catalog.ps1 new file mode 100644 index 00000000000000..4f8626c5205c4b --- /dev/null +++ b/eng/generate-catalog.ps1 @@ -0,0 +1,93 @@ +<# +.SYNOPSIS + Generates a catalog definition file (.cdf) and catalog file (.cat) for all .js files + in the specified root directory. Used for VS signing compliance - the .js files are + customer-modifiable and cannot be directly Authenticode-signed. + +.PARAMETER RootPath + Root directory to search for .js files recursively. + +.PARAMETER CatOutputPath + Full path for the output .cat file. +#> +param( + [Parameter(Mandatory)][string]$RootPath, + [Parameter(Mandatory)][string]$CatOutputPath, + [string]$WindowsSdkDir = '', + [switch]$ErrorIfMakecatNotFound +) + +$ErrorActionPreference = 'Stop' + +$cdfPath = [System.IO.Path]::ChangeExtension($CatOutputPath, '.cdf') + +$files = Get-ChildItem -Path $RootPath -Recurse -Filter '*.js' -File +if ($files.Count -eq 0) { + Write-Warning "No .js files found under $RootPath - skipping catalog generation." + exit 0 +} + +$cdf = @() +$cdf += '[CatalogHeader]' +$cdf += "Name=$CatOutputPath" +$cdf += 'CatalogVersion=2' +$cdf += 'HashAlgorithms=SHA256' +$cdf += '' +$cdf += '[CatalogFiles]' + +$i = 0 +foreach ($f in $files) { + $label = "js_${i}_" + ($f.Name -replace '[^\w\.-]', '_') + $cdf += "$label=$($f.FullName)" + $i++ +} + +$cdf | Set-Content -Path $cdfPath -Encoding ASCII +Write-Host "Generated CDF with $($files.Count) .js files at $cdfPath" + +$catDir = [System.IO.Path]::GetDirectoryName($CatOutputPath) +if (-not (Test-Path $catDir)) { + New-Item -ItemType Directory -Path $catDir -Force | Out-Null +} + +# Find makecat.exe - it ships with the Windows SDK and may not be on PATH. +$makecat = $null +if ($WindowsSdkDir -and (Test-Path $WindowsSdkDir)) { + $makecat = Get-ChildItem -Path (Join-Path $WindowsSdkDir 'bin') -Recurse -Filter 'makecat.exe' -File | + Where-Object { $_.DirectoryName -match 'x64' } | + Sort-Object DirectoryName -Descending | + Select-Object -First 1 +} + +if (-not $makecat) { + $makecat = Get-Command makecat.exe -ErrorAction SilentlyContinue +} + +if (-not $makecat) { + # Fallback: search common Windows SDK locations + $sdkRoot = "${env:ProgramFiles(x86)}\Windows Kits\10\bin" + if (Test-Path $sdkRoot) { + $makecat = Get-ChildItem -Path $sdkRoot -Recurse -Filter 'makecat.exe' -File | + Where-Object { $_.DirectoryName -match 'x64' } | + Sort-Object DirectoryName -Descending | + Select-Object -First 1 + } +} + +if (-not $makecat) { + if ($ErrorIfMakecatNotFound) { + throw "makecat.exe not found. Catalog signing requires the Windows SDK which must be available in CI builds." + } + Write-Warning "makecat.exe not found - skipping catalog generation. Catalog signing requires the Windows SDK." + exit 0 +} + +$makecatPath = if ($makecat -is [System.Management.Automation.CommandInfo]) { $makecat.Source } else { $makecat.FullName } +Write-Host "Using makecat.exe at: $makecatPath" + +& $makecatPath $cdfPath +if ($LASTEXITCODE -ne 0) { + throw "makecat.exe failed with exit code $LASTEXITCODE" +} + +Write-Host "Generated catalog file: $CatOutputPath" diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Mono.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Mono.sfxproj index f074aa4c2e5e06..1124e28af09246 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Mono.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Mono.sfxproj @@ -70,4 +70,29 @@ + + + + + <_CatOutputPath>$(ArtifactsObjDir)mono-pack\mono-runtime-js.cat + <_ErrorIfMakecatNotFound Condition="'$(ContinuousIntegrationBuild)' == 'true' or '$(OfficialBuild)' == 'true'">-ErrorIfMakecatNotFound + + + + + + + runtimes/$(RuntimeIdentifier)/native/mono-runtime-js.cat + true + + + +