Skip to content

Commit 2d6b99d

Browse files
jesuszarateakoeplingerCopilot
authored
Add catalog signing for .js files for VS signing compliance (#1671)
* Add catalog signing for .js files for VS signing compliance The .js files in the Emscripten SDK are customer-modifiable toolchain files that cannot be directly Authenticode-signed (modifying a signed file breaks the signature). Instead, generate a .cat catalog file covering all .js files, which is signed with MicrosoftDotNet500 via the existing FileExtensionSignInfo entry for .cat files. The GenerateCatalogFiles target runs after ReallyBuild on Windows only (makecat.exe is a Windows SDK tool). It invokes eng/generate-catalog.ps1 which enumerates all .js files, generates a CDF, runs makecat.exe, and produces emscripten-js.cat in the SDK package directory so it ships alongside the files it covers. This fixes ~14,468 unsigned .js files flagged by VS signing compliance scans. * Error when makecat.exe is not found in CI/official builds Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Only log catalog message when file was actually produced Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Alexander Köplinger <alex.koeplinger@outlook.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 1751bd6 commit 2d6b99d

3 files changed

Lines changed: 117 additions & 1 deletion

File tree

eng/Signing.props

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
<FileExtensionSignInfo Include=".pyd" CertificateName="MicrosoftDotNet500" />
99
<FileExtensionSignInfo Include=".cat" CertificateName="MicrosoftDotNet500" />
1010

11-
<!-- We don't need to code sign .js files because they are not used in Windows Script Host. -->
11+
<!-- JS files are customer-modifiable Emscripten toolchain files. They cannot be
12+
Authenticode-signed because modifying a signed file breaks the signature.
13+
Instead, a catalog file (emscripten-js.cat) is generated and signed to provide
14+
integrity verification. See the GenerateCatalogFiles target in eng/emsdk.proj. -->
1215
<FileExtensionSignInfo Update=".js" CertificateName="None" />
1316

1417
<!--

eng/emsdk.proj

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,24 @@
365365
<Delete Files="@(DeleteCacheFiles)" />
366366
</Target>
367367

368+
<!--
369+
Generate a catalog (.cat) file covering all .js files in the SDK package.
370+
The .js files are customer-modifiable Emscripten toolchain files that cannot be
371+
directly Authenticode-signed. The .cat provides integrity verification without
372+
preventing modification. Only runs on Windows (makecat.exe is a Windows SDK tool)
373+
and only the Windows packs are inserted into VS.
374+
-->
375+
<Target Name="GenerateCatalogFiles" AfterTargets="ReallyBuild" Condition="$([MSBuild]::IsOSPlatform('Windows'))">
376+
<PropertyGroup>
377+
<_CatOutputPath>$(ArtifactsObjDir)upstream\emscripten\emscripten-js.cat</_CatOutputPath>
378+
<_ErrorIfMakecatNotFound Condition="'$(ContinuousIntegrationBuild)' == 'true' or '$(OfficialBuild)' == 'true'">-ErrorIfMakecatNotFound</_ErrorIfMakecatNotFound>
379+
</PropertyGroup>
380+
381+
<Exec Command="powershell.exe -NoProfile -ExecutionPolicy Bypass -Command &quot;&amp; '$(MSBuildThisFileDirectory)generate-catalog.ps1' -RootPath '$(ArtifactsObjDir)upstream' -CatOutputPath '$(_CatOutputPath)' -WindowsSdkDir '$(WindowsSdkDir)' $(_ErrorIfMakecatNotFound)&quot;" StandardOutputImportance="High" />
382+
383+
<Message Condition="Exists('$(_CatOutputPath)')" Importance="High" Text="Generated catalog file: $(_CatOutputPath)" />
384+
</Target>
385+
368386
<Target Name="ReallyPack" DependsOnTargets="Build" BeforeTargets="Pack">
369387
<Message Importance="High" Text="Creating nuget packages..." />
370388
<MSBuild Projects="$(MSBuildThisFileDirectory)nuget\Microsoft.NET.Runtime.Emscripten.Node\Microsoft.NET.Runtime.Emscripten.Node.pkgproj" Targets="Build" />

eng/generate-catalog.ps1

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<#
2+
.SYNOPSIS
3+
Generates a catalog definition file (.cdf) and catalog file (.cat) for all .js files
4+
in the specified root directory. Used for VS signing compliance - the .js files are
5+
customer-modifiable and cannot be directly Authenticode-signed.
6+
7+
.PARAMETER RootPath
8+
Root directory to search for .js files recursively.
9+
10+
.PARAMETER CatOutputPath
11+
Full path for the output .cat file.
12+
#>
13+
param(
14+
[Parameter(Mandatory)][string]$RootPath,
15+
[Parameter(Mandatory)][string]$CatOutputPath,
16+
[string]$WindowsSdkDir = '',
17+
[switch]$ErrorIfMakecatNotFound
18+
)
19+
20+
$ErrorActionPreference = 'Stop'
21+
22+
$cdfPath = [System.IO.Path]::ChangeExtension($CatOutputPath, '.cdf')
23+
24+
$files = Get-ChildItem -Path $RootPath -Recurse -Filter '*.js' -File
25+
if ($files.Count -eq 0) {
26+
Write-Warning "No .js files found under $RootPath - skipping catalog generation."
27+
exit 0
28+
}
29+
30+
$cdf = @()
31+
$cdf += '[CatalogHeader]'
32+
$cdf += "Name=$CatOutputPath"
33+
$cdf += 'CatalogVersion=2'
34+
$cdf += 'HashAlgorithms=SHA256'
35+
$cdf += ''
36+
$cdf += '[CatalogFiles]'
37+
38+
$i = 0
39+
foreach ($f in $files) {
40+
$label = "js_${i}_" + ($f.Name -replace '[^\w\.-]', '_')
41+
$cdf += "<hash>$label=$($f.FullName)"
42+
$i++
43+
}
44+
45+
$cdf | Set-Content -Path $cdfPath -Encoding ASCII
46+
Write-Host "Generated CDF with $($files.Count) .js files at $cdfPath"
47+
48+
$catDir = [System.IO.Path]::GetDirectoryName($CatOutputPath)
49+
if (-not (Test-Path $catDir)) {
50+
New-Item -ItemType Directory -Path $catDir -Force | Out-Null
51+
}
52+
53+
# Find makecat.exe - it ships with the Windows SDK and may not be on PATH.
54+
# Prefer WindowsSdkDir if passed from MSBuild (not available in this repo's build
55+
# context since it uses Microsoft.Build.Traversal, but may be set in other builds).
56+
$makecat = $null
57+
if ($WindowsSdkDir -and (Test-Path $WindowsSdkDir)) {
58+
$makecat = Get-ChildItem -Path (Join-Path $WindowsSdkDir 'bin') -Recurse -Filter 'makecat.exe' -File |
59+
Where-Object { $_.DirectoryName -match 'x64' } |
60+
Sort-Object DirectoryName -Descending |
61+
Select-Object -First 1
62+
}
63+
64+
if (-not $makecat) {
65+
$makecat = Get-Command makecat.exe -ErrorAction SilentlyContinue
66+
}
67+
68+
if (-not $makecat) {
69+
# Fallback: search common Windows SDK locations
70+
$sdkRoot = "${env:ProgramFiles(x86)}\Windows Kits\10\bin"
71+
if (Test-Path $sdkRoot) {
72+
$makecat = Get-ChildItem -Path $sdkRoot -Recurse -Filter 'makecat.exe' -File |
73+
Where-Object { $_.DirectoryName -match 'x64' } |
74+
Sort-Object DirectoryName -Descending |
75+
Select-Object -First 1
76+
}
77+
}
78+
79+
if (-not $makecat) {
80+
if ($ErrorIfMakecatNotFound) {
81+
throw "makecat.exe not found. Catalog signing requires the Windows SDK which must be available in CI builds."
82+
}
83+
Write-Warning "makecat.exe not found - skipping catalog generation. Catalog signing requires the Windows SDK."
84+
exit 0
85+
}
86+
87+
$makecatPath = if ($makecat -is [System.Management.Automation.CommandInfo]) { $makecat.Source } else { $makecat.FullName }
88+
Write-Host "Using makecat.exe at: $makecatPath"
89+
90+
& $makecatPath $cdfPath
91+
if ($LASTEXITCODE -ne 0) {
92+
throw "makecat.exe failed with exit code $LASTEXITCODE"
93+
}
94+
95+
Write-Host "Generated catalog file: $CatOutputPath"

0 commit comments

Comments
 (0)