Skip to content

Sign Windows releases with SignPath Foundation - #536

Merged
mgth merged 3 commits into
masterfrom
sign-releases-signpath
Aug 3, 2026
Merged

Sign Windows releases with SignPath Foundation#536
mgth merged 3 commits into
masterfrom
sign-releases-signpath

Conversation

@mgth

@mgth mgth commented Aug 3, 2026

Copy link
Copy Markdown
Owner

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:

Release Certificate table (RVA/size)
LittleBigMouse_5.4.1.exe 0 / 0 — unsigned
LittleBigMouse_5.6.0.exe 0 / 0 — unsigned

Same 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 .exe alone would leave LittleBigMouse.Ui.Avalonia.exe and LittleBigMouse.Hook.exe unsigned inside it, and those are what Windows judges once they are on disk. Hence the new SourceDir define 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 not Valid — a signing request can report success having signed nothing that matters.

Three things worth reviewing

SIGNPATH_PROJECT_SLUG is 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.CheckVersion downloads assets[0]. An SBOM asset named LittleBigMouse_x.y.z.cdx.json sorts 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 than github.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

  • SignPath action input names checked against action.yml at 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.
  • Its default completion timeout is 10 minutes, too short for a Foundation policy that waits on a human approval — raised to 3600s.
  • The .iss change 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.
  • The signing path itself cannot be exercised until SignPath is configured.

Blocking next step, outside the code: apply for the project at SignPath Foundation, then set SIGNPATH_API_TOKEN and the five variables listed in SIGNING.md.

🤖 Generated with Claude Code

mgth added 2 commits August 3, 2026 09:22
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.
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.
@mgth
mgth merged commit 2557791 into master Aug 3, 2026
2 checks passed
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.

Windows 11 Smart App Control completly blocked 5.6.0 install

1 participant