Skip to content

v0.3.0 — artefact integrity bundle

Choose a tag to compare

@TheCryptoDonkey TheCryptoDonkey released this 11 Apr 12:18
· 80 commits to main since this release

Artefact integrity bundle. Two new pre-publish gates and a rewired publish path that lets downstream consumers verify the registry tarball byte-for-byte against what CI built.

What's new

  • record-tarball packs the release artefact once into a known location, parses npm pack --json for the sha512 integrity, hashes the tarball with sha256, and writes tarball.meta for the rest of the pipeline to consume.
  • publish-npm now uploads the exact tarball recorded above rather than re-packing. The bytes the registry receives are byte-identical to the bytes the integrity block reports. On a clean re-run of an already-published release, the registry's dist.integrity is compared to the recorded value: a match exits silently, a mismatch fails the workflow loudly. That scenario is registry tarball substitution and you want to know about it on the next CI run.
  • update-release appends an Artefact integrity block to the GitHub Release body containing filename, size, sha256, sha512 (npm format), and a one-line curl | shasum recipe. Anyone can fetch the registry tarball and confirm byte-equivalence with what CI built.
  • verify-action-pins walks .github/workflows/*.yml in your repo and warns on any uses: owner/repo@ref line whose ref is not a 40-char hex SHA. Warn-only by default. New strict-action-pins: true input promotes warnings to a hard failure. forgesworn/release-action is exempt by name; see THREAT-MODEL.md for the rationale.

Migration

None required. The new gates are additive and verify-action-pins is warn-only by default. Existing v0.2.x consumers can bump their pin to v0.3.0 (or stay on @v0) without changing any caller-workflow input.

If you want the strict pin gate:

with:
  vector-test-command: npm run test:vectors
  strict-action-pins: true

Known limits

  • The recorded sha256 is a single-runner integrity anchor, not a reproducibility proof. Two runners building the same commit may still produce two different hashes today, due to embedded timestamps and path leakage. Cross-runner reproducible-build is a planned v0.4 theme. The integrity block defends against registry tarball substitution, which does not require build-level determinism to detect.
  • verify-action-pins cannot statically resolve dynamic uses: ${{ matrix.action }} lines and silently skips them. Audit those templates separately.

Verify a release tarball

Every release body now ends with a verify recipe like:

curl -sLO https://registry.npmjs.org/<pkg>/-/<pkg>-1.2.3.tgz
shasum -a 256 <pkg>-1.2.3.tgz

Compare the result to the sha256: line in the release body. They should match exactly.

Stats

  • 2 new step scripts (record-tarball.sh, verify-action-pins.sh)
  • 13 new bats tests (43 total, all passing)
  • shellcheck clean
  • Zero new dependencies; still pure bash + jq + gh + npm
  • ~1000 lines of bash across all step scripts (still inside the 30-minute audit budget)