Development record
abcd update verifies a downloaded binary only against the checksums.txt published in the same GitHub release (internal/core/update/update.go), so it catches corruption in transit but not a release page whose binary and checksums.txt were both replaced; the binary needs an independent check next cycle, such as a digest committed in the repository's history the way the plugin catalog now pins the plugin archive (adr-2609231048308186), or verification of the release's signed build-provenance attestation (a new verification dependency needs sign-off first). Ruled by the product thinker on 2026-09-23 (E5, 10:27Z): harden next cycle; this release keeps the same-page check.
abcd update verifies a downloaded binary only against the checksums.txt published in the same GitHub release (internal/core/update/update.go), so it catches corruption in transit but not a release page whose binary and checksums.txt were both replaced; the binary needs an independent check next cycle, such as a digest committed in the repository's history the way the plugin catalog now pins the plugin archive (adr-2609231048308186), or verification of the release's signed build-provenance attestation (a new verification dependency needs sign-off first). Ruled by the product thinker on 2026-09-23 (E5, 10:27Z): harden next cycle; this release keeps the same-page check.
Deferral 2026-09-29
Deferred past v0.11.1: ruling still owed to the product thinker (re-deferred at v0.11.1 by run A's major-triage lane): ruling E5 (2026-09-23) asks for a check independent of the release page and leaves the mechanism open. The release already publishes SLSA build-provenance attestations over the binaries and checksums.txt (release.yml, actions/attest), so the candidates are verifying that attestation (a sigstore verification dependency needing sign-off, or a runtime dependency on gh attestation verify) or a digest committed in the repository's history (no new Go dependency, but the release chain must first commit per-binary digests; the catalog pins only the plugin archive, adr-2609231048308186). Owed: that choice, then a lane of its own.
Remedy grounds (2026-09-29)
- The threat is a release page whose binary and checksums.txt are replaced together; both candidate routes break that because neither reads its trust from the same page. gh attestation verify checks a signed attestation against --repo and --signer-workflow and works offline with --bundle: https://cli.github.com/manual/gh_attestation_verify (consulted 2026-09-29); sigstore-go describes itself as stable and passing the sigstore-conformance suite: https://github.com/sigstore/sigstore-go (consulted 2026-09-29).
- No route is picked: the choice and the dependency sign-off are owed rulings (rulings-owed C). Rejected: an offline signing key (minisign, itd-108), which adds key custody rather than removing the same-origin trust.
Grounds
- pursued: a replaced binary with a matching replaced checksums.txt is now refused before the swap because no provenance signed by release.yml names its bytes; shown wrong if a binary that release.yml did not build, or one signed by another repository or workflow, is ever swapped in
Frontmatter
| id | iss-2609231050273096 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-2609231050273096-abcd-update-verifies-a-downloaded-binary.md
open on GitHub ↗ · commit history ↗
mentions6
- adr-2609231048308186The catalog pins the latest release's plugin archive
- adr-2611011813195749abcd never runs a foreign executable under its own name, and no code that writes records is loaded at run time
- dcn-26092300000000182026-09-23 — The two rulings that close how a release reaches `/plugin update` (product thinker, rulings E4 and E5 of the run A interview, 10:23Z and 10:27Z), recorded beside the build they govern; the E1 to E3 entry left E4 owed. E4, the contributor entry, 10:23Z: there is no second, development entry in the marketplace catalog. The public listing carries the pinned release archive alone, and contributors load the plugin from their own checkout, a step documented for contributors only (`CONTRIBUTING.md`), never in the user docs. E5, binary upgrade integrity, raised by the product thinker in E1, 10:27Z: `abcd update` verifies a downloaded binary only against the same release's `checksums.txt`, which catches corruption but not a release page whose binary and checksums were both replaced. A check independent of that release, such as a digest committed in the repository's history or a signed build attestation (a new verification dependency needs sign-off), is next-cycle work; this release keeps the same-page check. It is captured as iss-2609231050273096, deferred past v0.9.0 with this ruling as its reason.
- iss-2610120617515834abcd ahoy install promotes an owned copy of the abcd binary (internal/core/ahoy/owned_copy.go) after checking it only against checksums.txt from the same release page, the weakness iss-2609231050273096 fixed for abcd update: whoever can change the release page can swap the binary and its checksum together. Found by the E5 fix lane on 2026-10-12.
- iss-2610120617521209The plugin's first-run bootstrap (hooks/bootstrap.sh) and the install one-liner the site serves (site-src/install.sh.tmpl) download an abcd binary and check it only against checksums.txt from the same release page, the weakness iss-2609231050273096 fixed for abcd update in Go. A shell script cannot run the in-process provenance check, so the fix needs a design choice (for example: verify with gh attestation verify when gh is present and refuse or warn without it; or verify with a previously installed, already-verified abcd). Found by the E5 fix lane on 2026-10-12.
- itd-108The plugin installs from the curated release artifact, not the repo, and every cut release reaches users automatically