Windows: signed installer without the SmartScreen warning, and winget, Scoop and Chocolatey #76

Open
opened 2026-11-12 12:58:39 +01:00 by thatrichan · 1 comment
Owner

Today revue.exe and …-setup.exe are unsigned. SmartScreen shows "Windows protected your PC / Unknown publisher" and some antivirus tools flag the download. There's also no way to install Revue with a Windows package manager.

Part 1: Code signing

Which certificate

Since 2023 every publicly trusted code-signing key must live in an HSM (a cloud service or a token), so a .pfx in a CI secret is no longer an option. EV certificates no longer skip SmartScreen either (since 2024), so a cheaper OV certificate is enough: reputation builds up with downloads either way. The options for us:

Option Cost Fits?
Certum Open Source Code Signing (cloud, SimplySign) ~€50–70 first year, cheaper renewals Individuals in the EU, open source projects (we're MIT/Apache). Risk: SimplySign is hard to use headless in CI, so check this before buying.
Azure Artifact Signing (formerly Trusted Signing) ~$10/month The best tooling, but individuals only in the US/Canada. It works only if we sign as a registered organization (EU is OK).
SignPath Foundation free for OSS Requires builds on CI it supports (GitHub Actions and others), not Forgejo Actions, so it would need a GitHub mirror that builds Windows.
OV from a commercial CA with cloud signing (e.g. SSL.com eSigner) ~$300+/year Works anywhere, and headless CI is supported.

Recommendation: Certum Open Source if its cloud signing can run headless (check it with jsign or osslsigncode with PKCS#11). Otherwise Azure if we have a company, otherwise SSL.com eSigner.

Where to sign (all on Linux, in the existing windows job)

  • Use jsign (Java, one jar, supports PKCS#11 / Azure / eSigner) or osslsigncode in the cargo-xwin container, with an RFC 3161 timestamp.
  • In task package PLATFORM=windows: sign revue.exe before it goes into the zip and the NSIS installer, sign the uninstaller from inside NSIS (!uninstfinalize, NSIS 3.08+), then sign …-setup.exe. Skip all of it when the secrets are missing, so local builds keep working.
  • The in-app updater installs the exe from the zip, so updates are signed too and nothing else changes.

Part 2: Package managers

First, the updater must keep the installed version in step

NSIS writes DisplayVersion to HKCU\…\Uninstall\Revue (packaging/revue.nsi:54), but the self-updater (src/update.rs:342) only swaps the exe. winget and Chocolatey read that version, so after a self-update they think an old version is installed and offer an upgrade. Fix this in one of two ways:

  • (recommended) On Windows, have the updater download the signed …-setup.exe and run it silently (/S), so the installer handles the files, the registry and the shortcuts in one place; or
  • also update DisplayVersion (and InstallLocation if it changed) after swapping the exe.

winget (first)

  • A manifest for the per-user NSIS installer: InstallerType: nullsoft, Scope: user, silent /S, UpgradeBehavior: install, and the Forgejo release asset URL (the repo is public).
  • Submit and update with Komac (Rust, runs on Linux): komac update <Id> --version X.Y.Z --urls … --submit from release.yml, with a GitHub token (WINGET_GITHUB_TOKEN) that opens the PR on microsoft/winget-pkgs. The first submission is by hand.
  • Unsigned packages are accepted, but signing (part 1) makes Microsoft's validation and Defender scans less likely to flag us.

Scoop (cheap, fits the portable zip)

  • Our own bucket repo scoop-revue with revue.json: the zip, bin: revue.exe, a shortcut, plus checkver/autoupdate pointing at the Forgejo releases API. Scoop installs into ~/scoop/apps. That folder is writable, but the updater should leave it to Scoop: detect a Scoop install from the exe's path (…\scoop\apps\…) the same way the Linux issue generalizes managed_by_nix.

Chocolatey (last)

  • A revue package (nuspec + chocolateyInstall.ps1 running the setup with /S and the checksum). choco pack and push run in the chocolatey/choco Linux image. Every version goes through community moderation (days), so it's the slowest channel. Do it if users ask.

Docs

Add winget, Scoop and Chocolatey to docs/getting-started.md (Install on Windows), the README table, and docs/updates.md (which installs update themselves and which update with their package manager).

Decisions for you

  • Which certificate route (and do we sign as an individual or as a company)?
  • Updater on Windows: run the silent installer (recommended), or keep swapping the exe and update the registry?
  • Which package managers: winget + Scoop now, Chocolatey later?

Order

Updater (DisplayVersion) → signing → winget → Scoop → docs → Chocolatey.

Today `revue.exe` and `…-setup.exe` are unsigned. SmartScreen shows "Windows protected your PC / Unknown publisher" and some antivirus tools flag the download. There's also no way to install Revue with a Windows package manager. ## Part 1: Code signing ### Which certificate Since 2023 every publicly trusted code-signing key must live in an HSM (a cloud service or a token), so a .pfx in a CI secret is no longer an option. EV certificates no longer skip SmartScreen either (since 2024), so a cheaper OV certificate is enough: reputation builds up with downloads either way. The options for us: | Option | Cost | Fits? | |---|---|---| | **Certum Open Source Code Signing** (cloud, SimplySign) | ~€50–70 first year, cheaper renewals | Individuals in the EU, open source projects (we're MIT/Apache). Risk: SimplySign is hard to use headless in CI, so **check this before buying**. | | **Azure Artifact Signing** (formerly Trusted Signing) | ~$10/month | The best tooling, but individuals only in the US/Canada. It works only if we sign as a registered organization (EU is OK). | | **SignPath Foundation** | free for OSS | Requires builds on CI it supports (GitHub Actions and others), not Forgejo Actions, so it would need a GitHub mirror that builds Windows. | | OV from a commercial CA with cloud signing (e.g. SSL.com eSigner) | ~$300+/year | Works anywhere, and headless CI is supported. | Recommendation: Certum Open Source if its cloud signing can run headless (check it with jsign or osslsigncode with PKCS#11). Otherwise Azure if we have a company, otherwise SSL.com eSigner. ### Where to sign (all on Linux, in the existing `windows` job) - Use [jsign](https://ebourg.github.io/jsign/) (Java, one jar, supports PKCS#11 / Azure / eSigner) or `osslsigncode` in the `cargo-xwin` container, with an RFC 3161 timestamp. - In `task package PLATFORM=windows`: sign `revue.exe` **before** it goes into the zip and the NSIS installer, sign the **uninstaller** from inside NSIS (`!uninstfinalize`, NSIS 3.08+), then sign `…-setup.exe`. Skip all of it when the secrets are missing, so local builds keep working. - The in-app updater installs the exe from the zip, so updates are signed too and nothing else changes. ## Part 2: Package managers ### First, the updater must keep the installed version in step NSIS writes `DisplayVersion` to `HKCU\…\Uninstall\Revue` (`packaging/revue.nsi:54`), but the self-updater (`src/update.rs:342`) only swaps the exe. winget and Chocolatey read that version, so after a self-update they think an old version is installed and offer an upgrade. Fix this in one of two ways: - **(recommended)** On Windows, have the updater download the signed `…-setup.exe` and run it silently (`/S`), so the installer handles the files, the registry and the shortcuts in one place; or - also update `DisplayVersion` (and `InstallLocation` if it changed) after swapping the exe. ### winget (first) - A manifest for the per-user NSIS installer: `InstallerType: nullsoft`, `Scope: user`, silent `/S`, `UpgradeBehavior: install`, and the Forgejo release asset URL (the repo is public). - Submit and update with [Komac](https://github.com/russellbanks/Komac) (Rust, runs on Linux): `komac update <Id> --version X.Y.Z --urls … --submit` from `release.yml`, with a GitHub token (`WINGET_GITHUB_TOKEN`) that opens the PR on `microsoft/winget-pkgs`. The first submission is by hand. - Unsigned packages are accepted, but signing (part 1) makes Microsoft's validation and Defender scans less likely to flag us. ### Scoop (cheap, fits the portable zip) - Our own bucket repo `scoop-revue` with `revue.json`: the zip, `bin: revue.exe`, a shortcut, plus `checkver`/`autoupdate` pointing at the Forgejo releases API. Scoop installs into `~/scoop/apps`. That folder is writable, but the updater should leave it to Scoop: detect a Scoop install from the exe's path (`…\scoop\apps\…`) the same way the Linux issue generalizes `managed_by_nix`. ### Chocolatey (last) - A `revue` package (nuspec + `chocolateyInstall.ps1` running the setup with `/S` and the checksum). `choco pack` and `push` run in the `chocolatey/choco` Linux image. Every version goes through community moderation (days), so it's the slowest channel. Do it if users ask. ### Docs Add winget, Scoop and Chocolatey to `docs/getting-started.md` (Install on Windows), the README table, and `docs/updates.md` (which installs update themselves and which update with their package manager). ## Decisions for you - Which certificate route (and do we sign as an individual or as a company)? - Updater on Windows: run the silent installer (recommended), or keep swapping the exe and update the registry? - Which package managers: winget + Scoop now, Chocolatey later? ## Order Updater (DisplayVersion) → signing → winget → Scoop → docs → Chocolatey.
Author
Owner

Package managers, done ahead of signing (7a82743):

  • winget: thatrichan.Revue 0.42.0 submitted, https://github.com/microsoft/winget-pkgs/pull/478503 (CLA signed). Later versions: release.yml's package-managers job runs Komac, which needs the secret WINGET_GITHUB_TOKEN.
  • Scoop: the bucket thatrichan/scoop-revue is filled in from packaging/scoop/revue.json at each release. The repository still has to be created.
  • Updater: leaves Scoop installs to Scoop, and updates DisplayVersion in Installed apps after updating itself.
  • Chocolatey: waiting for an account and API key.

Signing is still open.

Package managers, done ahead of signing (7a82743): - **winget:** `thatrichan.Revue` 0.42.0 submitted, https://github.com/microsoft/winget-pkgs/pull/478503 (CLA signed). Later versions: release.yml's `package-managers` job runs Komac, which needs the secret `WINGET_GITHUB_TOKEN`. - **Scoop:** the bucket `thatrichan/scoop-revue` is filled in from `packaging/scoop/revue.json` at each release. The repository still has to be created. - **Updater:** leaves Scoop installs to Scoop, and updates `DisplayVersion` in Installed apps after updating itself. - **Chocolatey:** waiting for an account and API key. Signing is still open.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
thatrichan/revue#76
No description provided.