From d504cc3312b320cae869a5decd28118b084ffd49 Mon Sep 17 00:00:00 2001 From: "jason.mei" Date: Wed, 12 Aug 2026 12:22:26 +0800 Subject: [PATCH] fix: verify release checksums during install --- .github/workflows/release.yml | 9 +++++++- install.ps1 | 13 +++++++++++ install.sh | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 267af49..18745a1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,6 +66,12 @@ jobs: else tar -C bin -czf "dist/ucloud-sandbox-cli_${GOOS}_${GOARCH}.tar.gz" ucloud-sandbox-cli fi + if [ "$GOOS" = "windows" ]; then + asset="dist/ucloud-sandbox-cli_${GOOS}_${GOARCH}.zip" + else + asset="dist/ucloud-sandbox-cli_${GOOS}_${GOARCH}.tar.gz" + fi + sha256sum "$asset" | awk '{ print $1 }' > "${asset}.sha256" - name: Upload artifact uses: actions/upload-artifact@v4 @@ -74,6 +80,7 @@ jobs: path: | dist/*.tar.gz dist/*.zip + dist/*.sha256 if-no-files-found: error release: @@ -100,7 +107,7 @@ jobs: GH_REPO: ${{ github.repository }} TAG_NAME: ${{ github.ref_name }} run: | - gh release create "${TAG_NAME}" dist/*.tar.gz dist/*.zip \ + gh release create "${TAG_NAME}" dist/*.tar.gz dist/*.zip dist/*.sha256 \ --draft \ --verify-tag \ --title "${TAG_NAME}" \ diff --git a/install.ps1 b/install.ps1 index 83a27c4..63587a3 100644 --- a/install.ps1 +++ b/install.ps1 @@ -112,9 +112,11 @@ $downloadUrl = if ($Version -eq "latest") { } else { "$releaseBaseUrl/download/$Version/$assetName" } +$checksumUrl = "$downloadUrl.sha256" $targetBinary = Join-Path $InstallDir "$BinaryName.exe" $tempDir = Join-Path ([IO.Path]::GetTempPath()) "$BinaryName-install-$([Guid]::NewGuid().ToString('N'))" $archivePath = Join-Path $tempDir $assetName +$checksumPath = "$archivePath.sha256" $extractDir = Join-Path $tempDir "extract" Write-Host "" @@ -135,6 +137,17 @@ try { Write-Info "Downloading $BinaryName..." Invoke-WebRequest -Uri $downloadUrl -OutFile $archivePath -UseBasicParsing + Invoke-WebRequest -Uri $checksumUrl -OutFile $checksumPath -UseBasicParsing + + Write-Info "Verifying release SHA256..." + $expectedHash = (Get-Content -LiteralPath $checksumPath -Raw).Trim().ToLowerInvariant() + if ($expectedHash -notmatch "^[0-9a-f]{64}$") { + throw "Release checksum must contain exactly 64 hexadecimal characters." + } + $actualHash = (Get-FileHash -LiteralPath $archivePath -Algorithm SHA256).Hash.ToLowerInvariant() + if ($actualHash -ne $expectedHash) { + throw "SHA256 verification failed for the downloaded release asset." + } Write-Info "Installing $BinaryName to $InstallDir..." Expand-Archive -LiteralPath $archivePath -DestinationPath $extractDir -Force diff --git a/install.sh b/install.sh index bdae88d..dda1ed5 100755 --- a/install.sh +++ b/install.sh @@ -158,6 +158,40 @@ download() { fi } +verify_sha256() { + file="$1" + checksum_file="$2" + expected="$(tr -d '[:space:]' <"$checksum_file" | tr '[:upper:]' '[:lower:]')" + + case "$expected" in + *[!0-9a-f]* | "") + error "Release checksum is invalid." + exit 1 + ;; + esac + if [ "${#expected}" -ne 64 ]; then + error "Release checksum must contain exactly 64 hexadecimal characters." + exit 1 + fi + + if has sha256sum; then + actual="$(sha256sum "$file" | awk '{ print $1 }')" + elif has shasum; then + actual="$(shasum -a 256 "$file" | awk '{ print $1 }')" + elif has openssl; then + actual="$(openssl dgst -sha256 "$file" | awk '{ print $NF }')" + else + error "No SHA256 implementation was found (sha256sum, shasum, or openssl)." + exit 1 + fi + + actual="$(printf '%s' "$actual" | tr '[:upper:]' '[:lower:]')" + if [ "$actual" != "$expected" ]; then + error "SHA256 verification failed for the downloaded release asset." + exit 1 + fi +} + make_tmp_dir() { if ! has mktemp; then error "mktemp was not found." @@ -360,6 +394,7 @@ main() { trap cleanup EXIT INT TERM archive="${TMP_DIR}/${BINARY_NAME}.tar.gz" + checksum="${archive}.sha256" info "Downloading ${BINARY_NAME}..." if ! download "$archive" "$URL"; then error "Download failed: $URL" @@ -368,6 +403,12 @@ main() { fi exit 1 fi + if ! download "$checksum" "${URL}.sha256"; then + error "Checksum download failed: ${URL}.sha256" + exit 1 + fi + info "Verifying release SHA256..." + verify_sha256 "$archive" "$checksum" info "Installing ${BINARY_NAME} to ${BIN_DIR}..." install_binary "$archive"