feat: update notifier and asobi upgrade self-update#37
Merged
Conversation
Phase A - notifier: after a command runs, print a one-line stderr notice when a newer release exists. Best-effort and non-blocking - consults a ~/.asobi/version_check.json cache (refreshed at most once/24h), stays silent on any error, on ASOBI_NO_UPDATE_CHECK, in CI, for dev builds, and for the version/upgrade/help commands. Phase B - `asobi upgrade`: download the release asset for this platform, verify it against the release checksums (fail closed), and atomically replace the running binary. Refuses package-manager-managed installs (Homebrew/Scoop/Nix) and read-only locations, pointing at the right tool. Verified end to end against the live v0.2.0 release: notifier fires for an older build, opt-out/CI/version paths stay silent, and a 0.1.0 binary self-upgrades to 0.2.0 after a real checksum-verified download.
From an adversarial review of the download/verify/replace path: - fail closed on an oversized extracted binary instead of silently truncating it (the checksum covers the archive, not the extracted binary), via readCapped in both tar.gz and zip paths. - refuse redirects to non-HTTPS URLs (no on-path downgrade to plaintext). - validate the release tag as semver before trusting it in a notice or interpolating it into a download URL; ignore a non-semver cached value. - on Windows, tell the user where the original binary is if rollback fails. Adds tests for oversized-extract rejection, HTTP-downgrade refusal, semver validation, and garbage-tag rejection. Live upgrade re-verified.
`asobi upgrade` now downloads checksums.txt.sig and verifies it against an embedded ed25519 public key (Go stdlib crypto/ed25519, no new dependency) before trusting checksums.txt. Chain of trust: signature -> checksums.txt -> asset, rooted in the embedded key, so a GitHub or CDN compromise alone can no longer forge an upgrade. Fails closed if the signature is missing, malformed, or does not verify. goreleaser signs checksums.txt via scripts/sign-checksums.sh using the ASOBI_SIGNING_KEY secret (a PEM ed25519 private key). Verified end to end with a local snapshot build: the produced signature verifies against the embedded public key and tampering is rejected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the two-phase self-update flow requested after cutting v0.2.0.
Phase A — update notifier
After a command runs, prints a one-line stderr notice when a newer release exists:
Best-effort and non-blocking:
~/.asobi/version_check.json, refreshes at most once/24h (avoids the 60/hr unauthenticated GitHub API limit).ASOBI_NO_UPDATE_CHECK, in CI, for dev builds, and forversion/upgrade/help.Phase B —
asobi upgradeDownloads the platform asset, verifies it against the release
checksums.txt(fail closed), and atomically replaces the running binary.asobibinary.Verification
httptest.gofmt/go vet/go test ./...clean.Security note / follow-up
Trust anchor is
checksums.txtover HTTPS from the GitHub release — same model asinstall.sh. Releases are not signed, so this doesn't defend against a GitHub/CDN compromise. Worth a follow-up to sign releases (cosign) and verify signatures here. A security-focused review of the download/replace path is welcome before merge.