Skip to content

chore(release): verify SHA512 against actual archive (#542)#543

Merged
kcenon merged 1 commit intodevelopfrom
chore/issue-542-verify-sha512-against-actual-archive
May 3, 2026
Merged

chore(release): verify SHA512 against actual archive (#542)#543
kcenon merged 1 commit intodevelopfrom
chore/issue-542-verify-sha512-against-actual-archive

Conversation

@kcenon
Copy link
Copy Markdown
Owner

@kcenon kcenon commented May 3, 2026

Closes #542

Part of kcenon/common_system#674.
References validated pattern in kcenon/common_system PR #676 (merged with 7/7 CI green).

What

Pins on-release-sync-registry.yml to the hardened merge commit of kcenon/common_system PR #676 (c90d4b828d3063989a850a785c7a60753c2b35ea) and adds an independent defense-in-depth verification job that runs after the reusable sync workflow.

The new job verify-sha512-against-archive re-fetches the published GitHub archive and compares its SHA512 against the SHA the registry portfile now declares for kcenon-container-system. On mismatch the workflow run fails with annotations naming both SHAs, before any cold-cache vcpkg consumer can hit an install failure.

Why

Detected via microsoft/vcpkg#51511 and kcenon/vcpkg-registry#87 - every kcenon port shipped a mismatched SHA512 because release automation never compared its computed value against the actual archive bytes. Cold-cache consumers (new CI runners, fresh users) hit 100% install failure when vcpkg-registry/ports/kcenon-container-system/portfile.cmake does not match https://github.com/kcenon/container_system/archive/refs/tags/v<version>.tar.gz.

This PR closes the detection gap for container_system.

Where

File Change
.github/workflows/on-release-sync-registry.yml Pin reusable workflow ref to PR #676 merge commit + add new verify-sha512-against-archive job that runs needs: sync

Audit summary (other workflows considered)

Workflow Touches portfile SHA? Action
on-release-sync-registry.yml Yes (delegates to reusable workflow that computes/writes SHA512 to portfile) Hardened (this PR)
release.yml No (multi-platform build/test/GitHub release; no portfile write) No change needed
validate-vcpkg-port.yml No (consumer-side find_package + build/install verification) No change needed
All other workflows (ci, coverage, sanitizers, fuzzing, sbom, benchmarks, docs, etc.) No Out of scope

Only on-release-sync-registry.yml participates in writing the portfile SHA, so a single-workflow hardening + parallel verification job satisfies the issue acceptance criteria.

How

The pinned reusable workflow (PR #676) inserts the SHA512 verify-against-archive step BETWEEN SHA computation and portfile commit, using file-based hashing (curl -fsSL --retry 3 -o <tmp>) rather than piping into sha512sum so a 404 cannot silently produce the empty-input SHA-512 constant cf83e1357eefb8bdf... (see kcenon auto-memory: curl_sha512_empty_input).

This PR's new verify-sha512-against-archive job adds a second, independent check that runs after the sync workflow has committed the new SHA: it re-downloads the published archive and the registry portfile, extracts the SHA from the portfile via regex, and compares. If the reusable workflow's internal verification is ever bypassed or regresses, this defensive job still catches the mismatch.

Runtime: ~2-3s on a typical container_system archive.

Test Plan

Reviewer validation

  1. After merge, cut a release tag (v0.x.y). The existing Sync Registry on Release workflow triggers both jobs:
    • sync (reusable workflow with internal SHA verification from PR #676)
    • verify-sha512-against-archive (this PR's defensive job)
  2. Inspect the verify-sha512-against-archive log for:
    Re-fetching https://github.com/kcenon/container_system/archive/refs/tags/v0.x.y.tar.gz for independent verification...
    SHA512 verified against https://github.com/kcenon/container_system/archive/refs/tags/v0.x.y.tar.gz
      <128-char hex digest>
    

Mismatch simulation (validated locally)

  • Match path (real archive SHA == registry SHA): job exits 0, prints verification line.
  • Mismatch path (registry SHA replaced with all-zero digest): job exits 1 with annotations SHA512 mismatch detected for v0.x.y / Registry portfile: 000... / GitHub archive: <real> / Cold-cache vcpkg consumers would hit install failure.
  • Bad URL path (nonexistent tag): curl -fsSL returns RC=22, the if ! branch fires exit 1 with Failed to download release archive for verification: <URL>. The download-to-file pattern (rather than a pipe) is required to make this work; piping into sha512sum would otherwise mask the curl failure with the empty-input hash.

YAML structure validated with js-yaml; job ordering confirmed (verify-sha512-against-archive has needs: sync).

Breaking Changes

None. Both changes are additive on a successful release: the pinned ref behaves identically to @main because the hardening is already in main; the new verification job adds ~2-3s and one log line per release. On a SHA mismatch (the failure mode this PR is designed to detect) it short-circuits the release before any consumer sees a stale SHA, which is the desired behavior.

Pin reusable sync workflow to the hardened merge commit from
kcenon/common_system PR #676 so the SHA512 verify-against-archive
hardening cannot silently regress, and add a defense-in-depth
verification job that re-fetches the published archive after sync
and compares its SHA512 against the SHA written to
vcpkg-registry/ports/kcenon-container-system/portfile.cmake.

Audit summary (per #542 acceptance criteria):

- on-release-sync-registry.yml: Yes (calls reusable workflow that
  computes/writes SHA512 via portfile commit). Hardened by this
  change: pinned ref + parallel verification job.
- release.yml: No (multi-platform build/test/GitHub release only;
  does not touch portfile SHA). No change needed.
- validate-vcpkg-port.yml: No (consumer-side find_package +
  build/install verification; does not write portfile). No change
  needed.
- All other workflows (ci, coverage, sanitizers, fuzzing, sbom,
  benchmarks, docs, etc.): No SHA computation or portfile writes.
  Out of scope.

The new verification job uses file-based hashing (curl -fsSL --retry
3 -o <tmp>) rather than piping into sha512sum, which prevents a 404
from silently producing the empty-input SHA-512 constant
cf83e1357eefb8bdf... (see kcenon auto-memory:
curl_sha512_empty_input).

On a healthy release the job adds ~2-3s and one log line. On a SHA
mismatch the job fails the workflow run with annotations naming both
the registry SHA and the archive SHA before consumers can hit a
cold-cache install failure.

Closes #542
Part of kcenon/common_system#674
References kcenon/common_system PR #676 (validated reference pattern)
@kcenon kcenon merged commit e5f7f4d into develop May 3, 2026
1 check passed
@kcenon kcenon deleted the chore/issue-542-verify-sha512-against-actual-archive branch May 3, 2026 12:57
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