Skip to content

fix: verify self-update archive checksums - #303

Open
k-nox wants to merge 7 commits into
mainfrom
luxbarker/api-318-sec-high-unsigned-self-update-binary-replaced-with-no
Open

fix: verify self-update archive checksums#303
k-nox wants to merge 7 commits into
mainfrom
luxbarker/api-318-sec-high-unsigned-self-update-binary-replaced-with-no

Conversation

@k-nox

@k-nox k-nox commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Verifies self-update release archives against GoReleaser's versioned SHA-256 checksum asset before extraction or replacement.
  • Applies the same fail-closed checksum verification to install.sh and removes temporary download artifacts after both successful and failed installations.
  • Adds Go and shell coverage for checksum parsing, mismatch handling, verification ordering, and installer cleanup.

Testing

  • go test ./... -count=1
  • go build ./...
  • bash -n install.sh
  • bash -n install_test.sh
  • bash install_test.sh
  • Built a disposable binary in a temporary directory and ran update against live GitHub release assets without replacing a production installation.
  • Mutation-tested the installer cleanup regression coverage by removing the cleanup trap and confirming the test failed for the expected leftover directory.

Security considerations

  • Verification occurs before archive extraction and binary replacement.
  • Missing checksum assets, missing archive entries, malformed digests, mismatches, and unavailable checksum tooling fail closed.
  • This protects against accidental corruption or replacement of the archive alone. A compromise that replaces both the release archive and its checksum asset remains out of scope and would require signed release metadata.

@k-nox
k-nox marked this pull request as ready for review July 13, 2026 17:41
@k-nox
k-nox requested a review from Copilot July 13, 2026 17:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens runpodctl self-update and installation flows by verifying downloaded release archives against the corresponding GoReleaser SHA-256 checksum asset before extraction or binary replacement.

Changes:

  • Add checksum-asset discovery + SHA-256 verification to runpodctl update prior to extraction/replacement.
  • Add checksum parsing + verification and temp-download cleanup behavior to install.sh.
  • Introduce Go and shell tests covering checksum parsing, mismatch handling, verification ordering, and installer cleanup.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
install.sh Downloads checksum asset, verifies archive digest before extraction, and cleans temp download artifacts.
install_test.sh Adds shell tests for checksum verification failure modes and cleanup behavior.
cmd/update.go Adds checksum asset lookup + SHA-256 verification for self-update archives.
cmd/update_test.go Adds unit tests for checksum asset naming, parsing, and verification helpers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread install.sh Outdated
Comment thread cmd/update.go Outdated
@promptless

promptless Bot commented Jul 13, 2026

Copy link
Copy Markdown

Promptless prepared a documentation update related to this change.

Triggered by runpodctl PR #303

Since the install script now verifies the downloaded release against its SHA-256 checksum before installing (and fails closed if no checksum tool is present), this adds a short note to the "Install script" tab of the runpodctl overview so users on minimal images know they need sha256sum (Linux) or shasum (macOS).

Review: Note sha256sum/shasum requirement for the runpodctl install script

@k-nox
k-nox force-pushed the luxbarker/api-318-sec-high-unsigned-self-update-binary-replaced-with-no branch from aa6ea9e to 6cad9c6 Compare July 17, 2026 16:22
@k-nox
k-nox requested review from brosenpod and justinwlin July 17, 2026 16:22
Comment thread cmd/update.go
}
file.Close()

checksumText, err := DownloadBytes(checksumAsset.Url)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checksum is not authenticated: The updater downloads the archive and its checksum from the same mutable GitHub release. An attacker able to replace the archive can replace the checksum asset too, so verification still succeeds. The installer has the same flaw at (install.sh:198). Use a signed provenance/checksum verified against an embedded public key, or pin a trusted digest from an independently authenticated channel.

@k-nox
k-nox force-pushed the luxbarker/api-318-sec-high-unsigned-self-update-binary-replaced-with-no branch from 6cad9c6 to 98e8aff Compare July 28, 2026 18:29
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.

3 participants