Skip to content

Verifying releases

Every release is built from a tagged commit by GitHub Actions; nobody builds or uploads release binaries by hand. Each release publishes:

Artifact What it’s for
dotsync_<version>_<os>_<arch>.tar.gz the binary, with LICENSE, README.md and CHANGELOG.md. <os> is darwin or linux, <arch> is amd64 or arm64
dotsync_<version>_<arch>.deb the Debian/Ubuntu package, also served by the APT repository
checksums.txt the SHA-256 of every archive and package
<archive or package>.sbom.json a software bill of materials for each archive and package
dotsync_<version>.intoto.jsonl the signed SLSA build provenance for every archive and package, also stored with GitHub. It ties each file to the workflow run, commit and repository that built it

The provenance is signed through Sigstore with the release workflow’s own short-lived identity. There’s no long-lived signing key that could leak.

This is the check that matters: it proves the file was built by this repository’s release workflow, from a commit in this repository.

  1. Install the GitHub CLI, version 2.49 or newer, and log in with gh auth login.

  2. Verify the archive you downloaded:

    Terminal window
    gh attestation verify dotsync_0.5.0_darwin_arm64.tar.gz --repo pungoyal/dotsync

    It ends with ✓ Verification succeeded!, and exits with status 0.

To see exactly which workflow run and commit built it:

Terminal window
gh attestation verify dotsync_0.5.0_darwin_arm64.tar.gz --repo pungoyal/dotsync --format json \
| jq '.[0].verificationResult.signature.certificate | {sourceRepositoryRef, sourceRepositoryDigest, runInvocationURI}'

The same signed provenance is attached to every release, so you can verify against the file instead of fetching it from GitHub’s attestation API:

Terminal window
gh attestation verify dotsync_0.5.0_darwin_arm64.tar.gz \
--bundle dotsync_0.5.0.intoto.jsonl --repo pungoyal/dotsync
Terminal window
curl -fsSLO https://github.com/pungoyal/dotsync/releases/download/v0.5.0/checksums.txt
shasum -a 256 --check --ignore-missing checksums.txt # macOS
sha256sum --check --ignore-missing checksums.txt # Linux

A checksum only proves the download wasn’t corrupted on the way. Someone who can replace the archive can replace checksums.txt too; only the provenance proves where the file came from.

Both install the files described above, so everything on this page applies to them too:

  • The Homebrew formula is generated by the release workflow from checksums.txt, and Homebrew refuses a download whose SHA-256 doesn’t match. It’s published to pungoyal/homebrew-tap, whose history shows every change.
  • The APT repository is rebuilt from the latest release’s .deb files after their checksums and provenance are verified. Its index is signed with the repository key, and apt refuses a package whose hash doesn’t match the signed index. To check a package against the release yourself, run gh attestation verify on the .deb from the release page.

Release binaries are built by GoReleaser with CGO_ENABLED=0 and -trimpath, stripped, and with the version, commit and commit date set at link time; file timestamps come from the commit, not the build machine. Building the tagged commit the same way, with the same Go version, reproduces the binary. go version -m dotsync shows the Go version and build settings of any binary.