Verify installer Authenticode signatures before running elevated#5
Merged
Merged
Conversation
DownloadAndInstallPackage handed any downloaded MSI/EXE straight to msiexec/the executable, running it elevated with no provenance check. The download only proves where the bytes came from, not who produced them: if the manifest or its host is compromised, an attacker-supplied installer runs as an elevated/SYSTEM process. Add SignatureVerifier (WinVerifyTrust + signer-certificate extraction) and gate InstallPackage on it for msi/exe items: the file must carry a signature that chains to a trusted root and, when configured, match an expected publisher. Unsigned/untrusted installers are refused unless AllowUnsigned is set; a publisher mismatch is never bypassed. Configurable via Intune CSP / Group Policy (new ADMX Security category: VerifyPackageSignatures, ExpectedPublisher, AllowUnsigned), the machine/user registry, and per-item manifest overrides (expectedPublisher, allowUnsigned). Defaults are secure. Mirrors the macOS SignatureVerifier.
This was referenced Jun 15, 2026
There was a problem hiding this comment.
Pull request overview
Adds an Authenticode provenance gate for Windows binary installers so MSI/EXE downloads are signature-verified (and optionally publisher-matched) before being executed elevated, reducing the risk of running attacker-supplied installers if a manifest/CDN is compromised.
Changes:
- Introduces
SignatureVerifierusingWinVerifyTrust+ signer certificate inspection and a policy decision helper (AllowUnsigned, publisher mismatch always denied). - Wires signature verification into the Windows install path for
msi/exe, with per-item manifest overrides (expectedPublisher,allowUnsigned). - Extends config/policy/ADMX(+ADML) + documentation to expose
VerifyPackageSignatures,ExpectedPublisher, andAllowUnsigned.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/BootstrapMate.Core/SignatureVerifier.cs | New WinVerifyTrust-based Authenticode verifier and policy decision logic. |
| src/BootstrapMate.Core/PolicyDetector.cs | Adds policy aliases for the new signature-verification settings. |
| src/BootstrapMate.Core/ConfigManager.cs | Loads/saves the new security settings from policy/registry and CLI override plumbing. |
| src/BootstrapMate.Core/BootstrapMateConfig.cs | Adds config fields + secure defaults for signature verification. |
| resources/en-US/BootstrapMate.adml | Adds localized strings/presentation for Security policies. |
| resources/BootstrapMate.admx | Adds new Security category and policies for signature verification configuration. |
| README.md | Documents signature verification behavior and relevant policy/registry keys. |
| Program.cs | Gates MSI/EXE installs on signature verification and supports per-item overrides. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| new("00AAC56B-CD44-11d0-8CC2-00C04FC295EE"); | ||
|
|
||
| private const uint WTD_UI_NONE = 2; | ||
| private const uint WTD_REVOKE_NONE = 0; |
| pPolicyCallbackData = IntPtr.Zero, | ||
| pSIPClientData = IntPtr.Zero, | ||
| dwUIChoice = WTD_UI_NONE, | ||
| fdwRevocationChecks = WTD_REVOKE_NONE, |
… choice - Use ToLowerInvariant() for the package-type switch to avoid locale-dependent comparison. - Add a comment explaining why WinVerifyTrust revocation checking is left off (OOBE/ESP often runs without reliable networking); the trusted-root chain is still verified, and the knob to enable WHOLECHAIN is noted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
InstallPackagehanded any downloaded MSI/EXE straight tomsiexec.exe/ direct execution — elevated, with no provenance check. The download only proves where the bytes came from (the configured URL), not who produced them. If the manifest or its host/CDN is compromised, an attacker-supplied installer runs as an elevated/SYSTEM process on every freshly provisioned PC. This is the Windows counterpart of the highest-severity audit finding.Fix
Add
SignatureVerifier(inBootstrapMate.Core) and gateInstallPackageon it formsi/exeitems:WinVerifyTrustconfirms the embedded Authenticode signature is present, intact, and chains to a trusted root.AllowUnsignedis set (then permitted with a warning).AllowUnsigned.Only
msi/exeare gated (PE/MSI files Authenticode can validate);nupkg/pkg/ps1keep their existing handling. Defaults are secure: verification on, no unsigned allowed.Configuration
Intune CSP / Group Policy via the bundled ADMX (new Security category):
VerifyPackageSignatures,ExpectedPublisher,AllowUnsigned. Also readable fromHKLM\SOFTWARE\BootstrapMate\Settings(machine) /HKCU(GUI), and overridable per manifest item (expectedPublisher,allowUnsigned).Mirrors the macOS
SignatureVerifier(pkgutil --check-signature) for cross-platform parity.Testing
dotnetis not available on the author's machine, so this was not built locally — relying on the repo CI (windows-latest, dotnet 10) to compile-verify. Please confirm the CI build is green before merging. The WinVerifyTrust P/Invoke and signer-cert extraction follow the standard Win32 pattern; logic mirrors the already-tested macOS implementation.Notes