Skip to content

fix(win): sign inner app binary, not just the installer#156

Merged
edospadoni merged 3 commits into
mainfrom
fix-windows-sign-inner-binary
Jun 4, 2026
Merged

fix(win): sign inner app binary, not just the installer#156
edospadoni merged 3 commits into
mainfrom
fix-windows-sign-inner-binary

Conversation

@edospadoni
Copy link
Copy Markdown
Member

@edospadoni edospadoni commented Jun 4, 2026

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:

Get-AuthenticodeSignature "C:\Program Files\NethLink\NethLink.exe"
# Status: NotSigned   SignatureType: None

Root cause

The release workflow signed Windows binaries as a post-build step with azure/trusted-signing-action, targeting dist/*.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.exe was 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) — signApp
  • Uninstall NethLink.exesignIf(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-action step becomes redundant and is removed; the existing AZURE_* secrets are passed to the build instead.

publisherName is set to the exact certificate Common Name (Nethesis Srl, read from the signed 1.4.5 installer). This matters beyond SAC: electron-updater uses publisherName to verify the signature of auto-updates, so it must match the cert CN.

Signing coverage

File Before (external action) After (electron-builder)
NethLink-<ver>-setup.exe (installer)
NethLink.exe (app)
Uninstall NethLink.exe

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.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-builder to sign Windows artifacts via win.azureSignOptions (Azure Trusted Signing) during the build.
  • Remove the post-build azure/trusted-signing-action step 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.

Comment thread electron-builder.yml Outdated
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).
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 4, 2026

Automatic builds from https://github.com/NethServer/nethlink/actions/runs/26942611382.
Commit: 2b771c5

Name Platform Link
win-app.exe Windows (x64) Link
macos-app-x64.dmg MacOS (x64) Link
macos-app-arm64.dmg MacOS (arm64) Link
linux-app.AppImage Linux (x64) Link

@edospadoni edospadoni merged commit 25e287f into main Jun 4, 2026
4 checks passed
@edospadoni edospadoni deleted the fix-windows-sign-inner-binary branch June 4, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants