Skip to content

Make every installer verifiable instead of asking for trust - #6

Merged
nazmiefearmutcu merged 1 commit into
mainfrom
feat/verifiable-releases
Jul 29, 2026
Merged

Make every installer verifiable instead of asking for trust#6
nazmiefearmutcu merged 1 commit into
mainfrom
feat/verifiable-releases

Conversation

@nazmiefearmutcu

Copy link
Copy Markdown
Owner

Why

A Reddit reply to the project was, in full: "AKA how to get malware on your pc."

That is a fair reaction to the front door as it stood. The README's first move was: download a
168 MB unsigned .dmg/.exe from an unknown GitHub account, then click past your OS's warning
(xattr -cr, SmartScreen → Run anyway). "It's open source" does not answer it — the source is
not what anyone downloaded
, and nothing connected the binary on the release page to the code in
this repo.

This closes that gap rather than arguing about it.

What changed

Build provenance (.github/workflows/release.yml). Every installer is signed with a SLSA
build-provenance attestation before it is uploaded, so the attested digest is the shipped digest.
Public and Sigstore-backed — it names the workflow, run and commit the file came from:

gh attestation verify <installer> -R nazmiefearmutcu/flowmap

A failure means the file did not come from this repository.

SHA256SUMS. Each matrix leg emits its checksum lines as a workflow artifact; the publish
job collects them into a single release asset, so shasum -a 256 -c SHA256SUMS works with no
tooling. (A parallel matrix can't produce one combined file on its own — hence the artifact hop.)

One file list. The installer list is resolved once (Collect the produced installers) and reused
by the attestation, the checksums and the upload, so those three can't drift apart.

SECURITY.md — what the app actually does, all verifiable in-tree: loopback-only bind
(a non-loopback FLOWMAP_HOST raises ValueError, it isn't quietly accepted), no telemetry,
no wallet/trading keys, no auto-updater or shell plugin, the exact outbound endpoints per market,
what it writes to disk and the 20 GB cap, what's inside the installer, and a private-advisory
reporting path.

README## Install now leads with running from source, a ### Verify your download section
sits directly under the download table, and the unsigned-app note points at the verification step
instead of only telling people how to click past the warning.

Notes

  • Attestations and SHA256SUMS cover the next tagged release onward; v1.3.0's assets predate
    them and will not verify. SECURITY.md and the README both say so explicitly.
  • New scopes on the build job: id-token: write + attestations: write. publish gains
    actions: read for download-artifact.
  • New actions are pinned to commit SHAs like the rest of the workflow:
    attest-build-provenance@0f67c3f (v4), upload-artifact@043fb46 (v7), download-artifact@3e5f45b (v8).
  • All new steps are gated on do_release == 'true', so a workflow_dispatch dry-run build is
    unaffected.

Verification

  • yaml.safe_load parses the workflow; job/step graph checked.
  • shellcheck -s bash clean on all four new/changed run: blocks.
  • The checksum → assemble → verify chain was run locally end to end against a fake bundle tree
    (unmerged download-artifact layout included): shasum -a 256 -c SHA256SUMSOK.
  • semgrep p/github-actions p/secrets — 48 rules, 0 findings.
  • Untested until a tag is cut: the attestation step itself and the artifact round-trip, which only
    run on a real release.

An unsigned 168 MB installer from an unknown GitHub account is, on its
face, indistinguishable from malware — and "the project is open source"
does not answer that, because the source is not what anyone downloaded.
Nothing tied the binary on the release page to the code in this repo.

The release workflow now signs a SLSA build-provenance attestation for
every installer *before* it uploads it, so the digest that is attested is
the digest that ships:

    gh attestation verify <installer> -R nazmiefearmutcu/flowmap

That is public and Sigstore-backed: it names the workflow, the run and the
commit the file was built from, and a failure means the file did not come
from here. Alongside it, each leg emits its checksum lines and the publish
job collects them into one SHA256SUMS release asset — the check that needs
no tooling at all (`shasum -a 256 -c SHA256SUMS`).

The file list is now resolved once and reused by the attestation, the
checksums and the upload, so those three cannot drift apart.

SECURITY.md writes down what the app actually does: loopback-only bind
(non-loopback FLOWMAP_HOST is rejected, not accepted quietly), no
telemetry, no wallet or trading keys, no auto-updater, the exact outbound
endpoints per market, and what it writes to disk. The README now leads
with running from source, and the unsigned-app warning points at the
verification step instead of just telling people to click past it.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@nazmiefearmutcu
nazmiefearmutcu merged commit 76fbebd into main Jul 29, 2026
1 check 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.

1 participant