Finding
Release Image runs on every push to main and pushes the configured image tag before signature/attestation verification and before creating the GitHub Release. Recent runs repeatedly built, pushed, signed, and attested 0.2.1, then hung in Verify image signature and attestations until cancellation:
GitHub Releases still stops at v0.1.11; v0.2.1 does not exist, while package.json and config/pools.yaml already point at 0.2.1. Because the release guard checks only for the GitHub Release, later main pushes can republish the same mutable image tag after a partial failure.
Impact
A deployable version tag can exist without a completed verification/release record, and routine merges can replace that tag repeatedly. Recovery is neither atomic nor idempotent.
Recommended work
- Trigger publication only from explicit release intent/version changes, not every unrelated main push.
- Preflight version uniqueness before any registry mutation.
- Push a unique staging reference or immutable digest, verify it, then promote the release tag.
- Bound each
cosign verify* operation and preserve diagnostics on timeout.
- Add a documented resumable path for the partially published
0.2.1 release.
Acceptance criteria
- Unrelated main pushes do not rebuild an existing version.
- Failed/cancelled verification cannot replace a released or candidate version tag.
- Verification steps have explicit timeouts and actionable logs.
- A successful run produces one immutable image digest plus matching tag and GitHub Release.
v0.2.1 is either safely completed or explicitly superseded through a documented recovery decision.
Evidence
.github/workflows/release-image.yml:3-7,21-23,139-234
package.json:3
config/pools.yaml:2-4
Finding
Release Imageruns on every push tomainand pushes the configured image tag before signature/attestation verification and before creating the GitHub Release. Recent runs repeatedly built, pushed, signed, and attested0.2.1, then hung inVerify image signature and attestationsuntil cancellation:GitHub Releases still stops at
v0.1.11;v0.2.1does not exist, whilepackage.jsonandconfig/pools.yamlalready point at0.2.1. Because the release guard checks only for the GitHub Release, later main pushes can republish the same mutable image tag after a partial failure.Impact
A deployable version tag can exist without a completed verification/release record, and routine merges can replace that tag repeatedly. Recovery is neither atomic nor idempotent.
Recommended work
cosign verify*operation and preserve diagnostics on timeout.0.2.1release.Acceptance criteria
v0.2.1is either safely completed or explicitly superseded through a documented recovery decision.Evidence
.github/workflows/release-image.yml:3-7,21-23,139-234package.json:3config/pools.yaml:2-4