fix(win): sign inner app binary, not just the installer#156
Merged
Conversation
Signing ran as a post-build step on dist/*.exe, which only covered the NSIS installer. The inner NethLink.exe and the uninstaller were packed unsigned, so Smart App Control blocked C:\Program Files\NethLink\NethLink.exe. Move signing into electron-builder via win.azureSignOptions so app exe, uninstaller and installer are all signed during packaging. publisherName matches the certificate CN (Nethesis Srl), also used by electron-updater to verify update signatures. Drop the now-redundant external signing step and bump the copyright year to 2026.
The Linux jobs rebuild uiohook-napi from source against Electron's ABI; since uiohook-napi 1.5.5 this needs the X11 dev headers (X11/keysym.h), which the ubuntu runner no longer provides. Install them before the build so the Linux dev and prod builds stop failing at electron-builder install-app-deps.
There was a problem hiding this comment.
Pull request overview
This PR updates the Windows release pipeline so that all extracted Windows binaries (the inner NethLink.exe, the uninstaller, and the NSIS installer) are signed during packaging, addressing Windows 11 Smart App Control blocking due to unsigned installed binaries.
Changes:
- Configure
electron-builderto sign Windows artifacts viawin.azureSignOptions(Azure Trusted Signing) during the build. - Remove the post-build
azure/trusted-signing-actionstep and instead pass Azure signing secrets into the Windows build step. - Update the copyright year.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
electron-builder.yml |
Adds win.azureSignOptions so electron-builder signs the inner app EXE, uninstaller, and installer during packaging. |
.github/workflows/build-prod.yml |
Removes external signing action and injects Azure signing env vars into the Windows build step. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
azureSignOptions was always-on in electron-builder.yml, so every Windows build (dev PRs, local build:win) required Azure credentials and failed without them (electron-builder throws when AZURE_TENANT_ID/CLIENT_ID/SECRET are missing). Move signing into electron-builder.release.yml, which extends the base config and adds win.azureSignOptions. Only the prod Windows job builds with --config electron-builder.release.yml, so dev/PR and local builds use the base config and stay unsigned, fast and credential-free. Also fix the Linux native build: uiohook-napi links -lX11 -lXrandr -lXtst -lXt, so install exactly those X11 dev headers (was missing libxrandr-dev).
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
On Windows 11, Smart App Control started blocking the app with:
It had worked for ~a month on release 1.4.5, then broke suddenly on a single machine. That is the expected behavior of Smart App Control: it is reputation-based and evaluated per-device in Microsoft's cloud. The device's SAC simply flipped from evaluation to enforcing mode, and at that point it started blocking unsigned binaries.
Verified on the affected machine:
Root cause
The release workflow signed Windows binaries as a post-build step with
azure/trusted-signing-action, targetingdist/*.exe. By the time that step ran,dist/contained only the installer (NethLink-<ver>-setup.exe). The inner application binary (NethLink.exe) and the uninstaller were already packed unsigned inside the NSIS installer.Result: the installer was signed (SmartScreen happy at download/install), but the extracted
C:\Program Files\NethLink\NethLink.exewas never signed — exactly the file SAC blocks.Fix
Move signing into electron-builder via
win.azureSignOptions(natively supported in electron-builder 26). electron-builder signs each binary at the right point in the pipeline:NethLink.exe(app) —signAppUninstall NethLink.exe—signIf(uninstallerPath)NethLink-<ver>-setup.exe(installer) —signIf(installerPath)All three route through the same Azure Trusted Signing manager, so the installer stays signed and the inner binaries are now signed too. The external
azure/trusted-signing-actionstep becomes redundant and is removed; the existingAZURE_*secrets are passed to the build instead.publisherNameis set to the exact certificate Common Name (Nethesis Srl, read from the signed 1.4.5 installer). This matters beyond SAC: electron-updater usespublisherNameto verify the signature of auto-updates, so it must match the cert CN.Signing coverage
NethLink-<ver>-setup.exe(installer)NethLink.exe(app)Uninstall NethLink.exe