Context
Surfaced during the multi-angle review of #192 (security pass, H-4).
In deploy.yml the release flow is split (good, least-privilege):
dxt-build (contents: read) builds dist/bx24-template-mcp.dxt and uploads it as a workflow artifact.
dxt-release (contents: write, only on v* tags) downloads that artifact and attaches it to the GitHub Release.
GitHub Actions artifacts are scoped to the same workflow run, so the trust boundary is reasonable — but there is no explicit integrity check that the .dxt attached to the Release is byte-for-byte the one that was built. A compromised runner between the two jobs could swap it.
Proposal
dxt-build: compute and record the digest, e.g. sha256sum dist/bx24-template-mcp.dxt | tee dist/bx24-template-mcp.dxt.sha256, and upload the .sha256 alongside the artifact (or expose it as a job output).
dxt-release: after download, re-compute and sha256sum --check before the softprops/action-gh-release step; fail loudly on mismatch.
- Optional: attach the
.sha256 file to the Release too, so downstream DXT installers can verify the bundle they pull from the Release page.
Acceptance
Refs
Context
Surfaced during the multi-angle review of #192 (security pass, H-4).
In
deploy.ymlthe release flow is split (good, least-privilege):dxt-build(contents: read) buildsdist/bx24-template-mcp.dxtand uploads it as a workflow artifact.dxt-release(contents: write, only onv*tags) downloads that artifact and attaches it to the GitHub Release.GitHub Actions artifacts are scoped to the same workflow run, so the trust boundary is reasonable — but there is no explicit integrity check that the
.dxtattached to the Release is byte-for-byte the one that was built. A compromised runner between the two jobs could swap it.Proposal
dxt-build: compute and record the digest, e.g.sha256sum dist/bx24-template-mcp.dxt | tee dist/bx24-template-mcp.dxt.sha256, and upload the.sha256alongside the artifact (or expose it as a joboutput).dxt-release: after download, re-compute andsha256sum --checkbefore thesoftprops/action-gh-releasestep; fail loudly on mismatch..sha256file to the Release too, so downstream DXT installers can verify the bundle they pull from the Release page.Acceptance
dxt-releasefails if the downloaded.dxtdigest differs from the one built indxt-build.sha256published as a Release assetRefs