Add catalog signing for unsigned apphost template files#127888
Add catalog signing for unsigned apphost template files#127888jesuszarate wants to merge 3 commits into
Conversation
The apphost template files (apphost.exe, singlefilehost.exe, comhost.dll) are intentionally unsigned because the .NET SDK modifies them at build time via HostWriter.CreateAppHost(). However, the Visual Studio signing scan flags them as non-compliant. This change adds a catalog file (.cat) containing SHA256 hashes of the template files. The catalog is signed with MicrosoftDotNet500 via Arcade signing and shipped alongside the templates in the AppHostPack NuGet package and MSI. This provides integrity verification for VS signing compliance without breaking the SDK workflow. Fixes the VS signing scan finding for 54 apphost template PE files across .NET 8/9/10 architectures. Related: dotnet#3694
There was a problem hiding this comment.
Copilot encountered an error: Your billing is not configured or you have Copilot licenses from multiple standalone organizations or enterprises. To use premium requests, select a billing entity via the GitHub site, under Settings > Copilot > Features.
| Condition="'$(TargetOS)' == 'windows'"> | ||
| <PropertyGroup> | ||
| <_CatStagingDir>$(IntermediateOutputPath)apphost-catalog\</_CatStagingDir> | ||
| <_CatalogFilePath>$(DotNetHostBinDir)apphost-templates.cat</_CatalogFilePath> |
There was a problem hiding this comment.
Fixed in 3ef521e — moved _CatalogFilePath from to so it's per-project and won't collide across parallel TFM/arch builds.
| <!-- Stage the unsigned template files in an isolated directory for catalog generation --> | ||
| <RemoveDir Directories="$(_CatStagingDir)" /> | ||
| <MakeDir Directories="$(_CatStagingDir)" /> | ||
| <Copy SourceFiles="$(DotNetHostBinDir)apphost.exe" DestinationFolder="$(_CatStagingDir)" Condition="Exists('$(DotNetHostBinDir)apphost.exe')" /> | ||
| <Copy SourceFiles="$(DotNetHostBinDir)singlefilehost.exe" DestinationFolder="$(_CatStagingDir)" Condition="Exists('$(DotNetHostBinDir)singlefilehost.exe')" /> | ||
| <Copy SourceFiles="$(DotNetHostBinDir)comhost.dll" DestinationFolder="$(_CatStagingDir)" Condition="Exists('$(DotNetHostBinDir)comhost.dll')" /> | ||
|
|
||
| <Exec Command="powershell.exe -NoProfile -NonInteractive -Command "New-FileCatalog -Path '$(_CatStagingDir)' -CatalogFilePath '$(_CatalogFilePath)' -CatalogVersion 2"" /> | ||
|
|
||
| <ItemGroup> | ||
| <FilesToPackage Include="$(_CatalogFilePath)" /> |
There was a problem hiding this comment.
Fixed in 3ef521e — added _StagedTemplateFiles ItemGroup that globs the staging directory. The Exec is now conditioned on @(_StagedTemplateFiles) != '' and FilesToPackage is conditioned on Exists('$(_CatalogFilePath)'), so neither runs if no template files were staged.
| <Copy SourceFiles="$(DotNetHostBinDir)singlefilehost.exe" DestinationFolder="$(_CatStagingDir)" Condition="Exists('$(DotNetHostBinDir)singlefilehost.exe')" /> | ||
| <Copy SourceFiles="$(DotNetHostBinDir)comhost.dll" DestinationFolder="$(_CatStagingDir)" Condition="Exists('$(DotNetHostBinDir)comhost.dll')" /> | ||
|
|
||
| <Exec Command="powershell.exe -NoProfile -NonInteractive -Command "New-FileCatalog -Path '$(_CatStagingDir)' -CatalogFilePath '$(_CatalogFilePath)' -CatalogVersion 2"" /> |
There was a problem hiding this comment.
Fixed in 3ef521e — added a _PowerShellCommand property that resolves to the full path via $(SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe when it exists, falling back to bare powershell.exe otherwise. This avoids PATH dependency on Windows build agents.
…ll path - Move _CatalogFilePath from $(DotNetHostBinDir) to $(IntermediateOutputPath) to avoid cross-target/parallel-build collisions in the shared output directory - Add _StagedTemplateFiles ItemGroup and condition the Exec on it being non-empty so the build is resilient to missing template inputs - Condition FilesToPackage on Exists() for the catalog file - Resolve powershell.exe via $(SystemRoot) full path to avoid PATH dependency, with fallback to bare powershell.exe
Summary
The apphost template files (\�pphost.exe, \singlefilehost.exe, \comhost.dll) are intentionally unsigned because the .NET SDK modifies them at build time via \HostWriter.CreateAppHost(). However, the Visual Studio signing scan (SignVerify) flags them as non-compliant unsigned PE binaries.
This change adds a catalog file (.cat) containing SHA256 hashes of the template files. The catalog is signed with \MicrosoftDotNet500\ via Arcade signing and shipped alongside the templates in the AppHostPack NuGet package and MSI. This provides integrity verification for VS signing compliance without breaking the SDK workflow.
Changes
Context
Risk
Low — This is a purely additive change. The unsigned template files are not modified. The .cat\ file is a new artifact that provides integrity verification only. The target only runs on Windows builds.