Sign Windows releases with SignPath Foundation - #536
Merged
Conversation
Smart App Control blocks the installer outright on Windows 11, with no "run anyway" for the user to click through (#535). Both 5.4.1 and 5.6.0 ship with an empty certificate table, so there is nothing for Windows to trust and nothing for a reputation to attach to; a stable publisher identity across releases is what fixes that, over the releases that follow it. Tag builds now send the build output to SignPath Foundation, verify what comes back, recompile the installer from the signed files, and sign that too. Signing only the setup .exe would leave the binaries inside it unsigned, and those are the ones Windows judges once they are on disk. Hence the new SourceDir define in the .iss: the release job points it at the signed files, and a local compile keeps reading the build output as before. Both stages fail closed on a publisher that is not SignPath Foundation or a signature that is not Valid, because a signing request can report success having signed nothing that matters. SIGNPATH_PROJECT_SLUG is the switch. Unset, a tag drafts the unsigned release exactly as it did before, so this can merge while the Foundation application is still pending; set, the signed job takes over and the unsigned path stands down. The draft carries the installer alone. The updater downloads assets[0], so an SBOM or a checksum file sorting ahead of LittleBigMouse_x.y.z.exe would be handed to every existing user in place of the setup program.
Both are conditions of the SignPath Foundation program, not paperwork added alongside it: the review expects a published code signing policy naming the Author/Reviewer/Approver roles, and a privacy policy for any application that touches the network. The privacy policy is written from what the code on this branch actually does, which is why it says the smart-TV pairing tokens are stored in plain text. An earlier draft claimed they were protected with DPAPI on Windows and AES-GCM on Unix; grepping for ProtectedData, DPAPI and AesGcm across the tree returns nothing, and both stores write plain JSON (SamsungTizenSettingsStore.cs:72, HisenseVidaaSettingsStore.cs:25). Samsung's file is created 0600 on Unix, which is the only protection there is, and Hisense's is not restricted at all. Shipping the encryption claim would have put a false statement in front of the reviewers of a program whose terms are about not compromising user privacy. Encrypting those tokens is worth doing; it is a change to the stores, not to a document, and does not belong in this commit.
This was referenced Aug 3, 2026
Their terms specify the sentence and the targets exactly, and the review compares against it. We linked signpath.io where the required text links about.signpath.io.
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.
Closes #535.
Why
Windows 11 Smart App Control blocks the installer outright, and unlike SmartScreen it offers no "run anyway" for the user to click through. The cause is not a 5.6.0 regression — I checked the certificate table in both PEs:
LittleBigMouse_5.4.1.exe0 / 0— unsignedLittleBigMouse_5.6.0.exe0 / 0— unsignedSame Inno Setup version, same section layout. 5.4.1 simply had six weeks and ~7000 downloads to accumulate reputation; 5.6.0 is an unknown hash with no signature to attach reputation to.
Signing is not an instant fix, and this PR should not be read as one: an OV certificate gives every release one stable publisher identity, and Microsoft's reputation accrues to that identity over subsequent releases. Immediate unblocking still needs a submission to Microsoft Security Intelligence.
What it does
On a
v*tag: sign the build output via SignPath Foundation → verify → recompile the installer from the signed files → sign the installer → verify → draft the release.The recompile is the point. Signing the setup
.exealone would leaveLittleBigMouse.Ui.Avalonia.exeandLittleBigMouse.Hook.exeunsigned inside it, and those are what Windows judges once they are on disk. Hence the newSourceDirdefine in the.iss: the release job points it at the signed files, a local compile keeps reading the build output exactly as before.Both stages fail closed on a publisher that is not
SignPath Foundation, or a signature that is notValid— a signing request can report success having signed nothing that matters.Three things worth reviewing
SIGNPATH_PROJECT_SLUGis the switch. While it is unset, a tag drafts the unsigned release exactly as it does today; once set, the signed job takes over and the unsigned path stands down. Without this, merging would block every release until the Foundation application is approved.The draft carries the installer and nothing else.
ApplicationUpdaterViewModel.CheckVersiondownloadsassets[0]. An SBOM asset namedLittleBigMouse_x.y.z.cdx.jsonsorts before.exe, so attaching the full bundle would hand every existing user a JSON file to execute in place of the setup program. The release name also stays the bare numeric version rather thangithub.ref_name.Deliberately out of scope, still sitting in the pr-513 work: CycloneDX SBOM, checksums, provenance attestation, self-contained publish, and the updater hardening in
ReleaseUpdateSecurity.cs. Attestation adds no release asset and is the easy next candidate.Verification
action.ymlat v2.2; pinned by digest (b9d91ead, confirmed to be that tag) since it is the only third-party action and the only step handed the token..isschange is not compiled in this PR's authoring; CI compiles the installer on every push since 9acd036, so this PR's own build validates it.Blocking next step, outside the code: apply for the project at SignPath Foundation, then set
SIGNPATH_API_TOKENand the five variables listed inSIGNING.md.🤖 Generated with Claude Code