wharfy 0.22.0 — what you ship carries provenance

Everything you ship is attested

release and publish running in GitHub Actions now attach build provenance to the sha256 of each thing that reaches a user — not only build artifacts. That includes install.sh, the script users pipe into their shell, and latest.json, the file their update check follows.

What is attested How a user checks it
archives / packages / bundles gh attestation verify <file> --repo acme/demo
install.sh / install.ps1 / latest.json same command — provenance is bound to the shipped bytes
the container image gh attestation verify oci://ghcr.io/acme/demo:1.2.0 --repo acme/demo

The host does not matter

Provenance is looked up by digest, not by where the file came from. If a tap, a scoop bucket, the AUR or your apt/rpm repo serves the same file, a user who got it there verifies it with the same command.

The image is attested during publish

An image can only be named by its manifest digest, and that digest does not exist until the registry has accepted the push. So the image is attested in publish, not in release.

No signing key, only permissions

Nothing to generate, store or rotate. The workflow needs these:

permissions:
  contents: write
  packages: write
  id-token: write        # signs the provenance (the identity Actions hands the workflow)
  attestations: write    # the attestation is stored on the repository

Nothing is attested from a laptop, and status says so instead of leaving you to find out later.

$ wharfy status
demo
attest: no OIDC token available — provenance is signed with the identity GitHub Actions hands the workflow, so nothing is attested from a laptop (in CI: permissions: id-token: write)

verify checks the provenance as a consumer

Attaching provenance is not proof that it works. A wrong signature format, an entry missing from the transparency log, or only some artifacts being covered all look fine from the publisher’s side. verify looks it up again the way a user would, and fails if it does not verify.

$ wharfy verify --version 1.2.0
✓ verified releases, script, attest
  attest: all 13 shipped artifacts on v1.2.0 carry verifiable provenance from this repository's workflow (signed, logged in rekor, and bound to the bytes users receive)
$ wharfy verify --version 1.2.0
✗ failed attest
  ! attest_unverified: attest: none of the 13 shipped artifacts on v1.2.0 carry build provenance — nothing proves they came from this repository's workflow; release attaches it when it runs in github actions with permissions: id-token: write / attestations: write

Asset contents are checked without downloading them

The default verify only checked that an asset with that name exists — contents were checked only with --install. A truncated upload, or an asset swapped after the fact, slipped through because the name was there. GitHub reports a digest per asset, so it is compared against what the checksums manifest declares, on every verify.

Before

$ wharfy verify --version 1.2.0
✓ verified releases
  releases 1.2.0: 13 assets present; the assets were not downloaded, so their contents are unchecked

After

$ wharfy verify --version 1.2.0
✓ verified releases
  releases 1.2.0: 13 assets present, and all 13 of them hash to what the checksums manifest says (compared against the digests github reports, without downloading them)

--install still downloads for real — it looks at the bytes a user actually receives. A release with nothing to compare against, a BYO path with no checksums manifest, still stops at probe.

Fixed

Getting it

brew upgrade wharfy / scoop update wharfy / go install github.com/ShiroDoromoto/wharfy/cmd/wharfy@latest. On Linux, from the apt / yum repo.