Summary
Every release page should let a player verify what they downloaded and see what antivirus engines say about it, without trusting our word: a SHA-256 per artefact and a VirusTotal analysis link per binary, written into the release notes by the release workflow itself. The Windows installation guide should explain the SmartScreen screen and the check.
Why
Unsigned installers get flagged (NekoJess on the Vintage Story Discord, 2026-09-04: Defender, Malwarebytes and Avast all warned, and two friends refuse anything an antivirus flags). Signing is a money and identity decision tracked in #351; this half costs nothing and helps today. A player who sees "2 of 70 engines, both heuristic" next to the hash of the file GitHub built is in a better place than one facing a bare warning.
What the player sees
- At the end of each release's notes, a section "Checksums and scans": one row per artefact with its SHA-256 and, for the binaries, a link to the VirusTotal analysis showing how many engines flagged it.
- In the Windows guide, a section on the "Windows protected your PC" screen: what it means for an unsigned installer, how to continue, how to compare the hash with
certutil -hashfile, and where the VirusTotal link is.
How it could work here
- A job in
.github/workflows/release.yml after the draft is built: download the assets, sha256sum each, submit the binaries to the VirusTotal API v3 (upload URL for files above 32 MB, free quota paced), poll the analysis with a bound, append the section to the draft's notes with gh release edit. Never fail the release on VirusTotal errors: warn and write the checksums alone.
- A
workflow_dispatch input with a tag so the job can run on an existing release.
- The logic in a small script under
scripts/ with unit tests on its pure parts (row formatting, section replacement, size threshold, pacing).
- The secret
VIRUSTOTAL_API_KEY is set on the repository.
Out of scope
Code signing (#351). A per-file allowlisting request to antivirus vendors.
Acceptance
Summary
Every release page should let a player verify what they downloaded and see what antivirus engines say about it, without trusting our word: a SHA-256 per artefact and a VirusTotal analysis link per binary, written into the release notes by the release workflow itself. The Windows installation guide should explain the SmartScreen screen and the check.
Why
Unsigned installers get flagged (NekoJess on the Vintage Story Discord, 2026-09-04: Defender, Malwarebytes and Avast all warned, and two friends refuse anything an antivirus flags). Signing is a money and identity decision tracked in #351; this half costs nothing and helps today. A player who sees "2 of 70 engines, both heuristic" next to the hash of the file GitHub built is in a better place than one facing a bare warning.
What the player sees
certutil -hashfile, and where the VirusTotal link is.How it could work here
.github/workflows/release.ymlafter the draft is built: download the assets,sha256sumeach, submit the binaries to the VirusTotal API v3 (upload URL for files above 32 MB, free quota paced), poll the analysis with a bound, append the section to the draft's notes withgh release edit. Never fail the release on VirusTotal errors: warn and write the checksums alone.workflow_dispatchinput with a tag so the job can run on an existing release.scripts/with unit tests on its pure parts (row formatting, section replacement, size threshold, pacing).VIRUSTOTAL_API_KEYis set on the repository.Out of scope
Code signing (#351). A per-file allowlisting request to antivirus vendors.
Acceptance