From 322ab6a5a98db5c230b7c90881b8b4baf4cee624 Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Fri, 7 Aug 2026 14:40:14 +0300 Subject: fix: verify stable release checksums --- website/install.ps1 | 17 ++++++++++++----- website/install.sh | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) (limited to 'website') diff --git a/website/install.ps1 b/website/install.ps1 index e5842dc8..b7ea80aa 100644 --- a/website/install.ps1 +++ b/website/install.ps1 @@ -154,12 +154,21 @@ function Get-ManifestAsset { throw "Release manifest does not include a binary for $Target." } + $sha256 = $null + $shaMapProperty = $Manifest.PSObject.Properties["sha256"] + if ($null -ne $shaMapProperty -and $null -ne $shaMapProperty.Value) { + $targetShaProperty = $shaMapProperty.Value.PSObject.Properties[$Target] + if ($null -ne $targetShaProperty -and -not [string]::IsNullOrWhiteSpace([string]$targetShaProperty.Value)) { + $sha256 = [string]$targetShaProperty.Value + } + } + $asset = $property.Value if ($asset -is [string]) { $url = [string]$asset return [PSCustomObject]@{ Url = $url - Sha256 = $null + Sha256 = $sha256 Format = if ($url.EndsWith(".zip", [System.StringComparison]::OrdinalIgnoreCase)) { "zip" } else { "exe" } } } @@ -180,10 +189,8 @@ function Get-ManifestAsset { throw "Release manifest asset $Target has unsupported format '$format'." } $shaProperty = $asset.PSObject.Properties["sha256"] - $sha256 = if ($null -eq $shaProperty -or [string]::IsNullOrWhiteSpace([string]$shaProperty.Value)) { - $null - } else { - [string]$shaProperty.Value + if ($null -ne $shaProperty -and -not [string]::IsNullOrWhiteSpace([string]$shaProperty.Value)) { + $sha256 = [string]$shaProperty.Value } return [PSCustomObject]@{ diff --git a/website/install.sh b/website/install.sh index 81c583ac..4e3ce40d 100755 --- a/website/install.sh +++ b/website/install.sh @@ -50,11 +50,38 @@ main() { exit } ')" + SHA256="$(printf '%s\n' "$MANIFEST" | awk -v target="\"${TARGET}\"" ' + /^[[:space:]]*"sha256"[[:space:]]*:/ { in_sha256 = 1; next } + in_sha256 && /^[[:space:]]*}/ { exit } + in_sha256 && index($0, target) { + sub(/^.*:[[:space:]]*"/, "") + sub(/".*$/, "") + print + exit + } + ')" VERSION="$(printf '%s\n' "$MANIFEST" | awk -F '"' '/^[[:space:]]*"version"[[:space:]]*:/ { print $4; exit }')" if [ -z "$URL" ]; then err "release manifest does not include a binary for ${TARGET}" fi + if [ "${#SHA256}" -ne 64 ]; then + err "release manifest does not include a valid SHA-256 checksum for ${TARGET}" + fi + if ! printf '%s\n' "$SHA256" | awk '/[^0-9A-Fa-f]/ { exit 1 }'; then + err "release manifest does not include a valid SHA-256 checksum for ${TARGET}" + fi + SHA256="$(printf '%s\n' "$SHA256" | awk '{ print tolower($0) }')" + + if command -v sha256sum >/dev/null 2>&1; then + SHA256_TOOL="sha256sum" + elif command -v shasum >/dev/null 2>&1; then + SHA256_TOOL="shasum" + elif command -v openssl >/dev/null 2>&1; then + SHA256_TOOL="openssl" + else + err "SHA-256 verification requires sha256sum, shasum, or openssl" + fi if [ -n "$VERSION" ]; then log "downloading v${VERSION}..." @@ -68,6 +95,15 @@ main() { err "download failed from ${URL}" fi + case "$SHA256_TOOL" in + sha256sum) ACTUAL_SHA256="$(sha256sum < "${TMP}/${BIN}" | awk '{ print $1 }')" ;; + shasum) ACTUAL_SHA256="$(shasum -a 256 < "${TMP}/${BIN}" | awk '{ print $1 }')" ;; + openssl) ACTUAL_SHA256="$(openssl dgst -sha256 < "${TMP}/${BIN}" | awk '{ print $NF }')" ;; + esac + if [ "$ACTUAL_SHA256" != "$SHA256" ]; then + err "downloaded Herdr checksum did not match" + fi + # install mkdir -p "$INSTALL_DIR" mv "${TMP}/${BIN}" "${INSTALL_DIR}/${BIN}" -- cgit v1.2.3