Skip to content

Commit 0de0005

Browse files
authored
fix(installer): add SHA256 checksum verification (#97)
1 parent 11d96e7 commit 0de0005

4 files changed

Lines changed: 145 additions & 7 deletions

File tree

.github/workflows/release.yml

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,38 @@ jobs:
209209
cd ..
210210
shell: bash
211211

212+
- name: Generate SHA256 checksum (Unix)
213+
if: matrix.goos != 'windows'
214+
run: |
215+
cd dist
216+
ARCHIVE_NAME="dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}"
217+
if command -v sha256sum &> /dev/null; then
218+
sha256sum "$ARCHIVE_NAME" > "$ARCHIVE_NAME.sha256"
219+
else
220+
shasum -a 256 "$ARCHIVE_NAME" > "$ARCHIVE_NAME.sha256"
221+
fi
222+
echo "Generated checksum:"
223+
cat "$ARCHIVE_NAME.sha256"
224+
shell: bash
225+
226+
- name: Generate SHA256 checksum (Windows)
227+
if: matrix.goos == 'windows'
228+
run: |
229+
$archiveName = "dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}"
230+
$archivePath = "dist/$archiveName"
231+
$hash = (Get-FileHash -Path $archivePath -Algorithm SHA256).Hash.ToLower()
232+
"$hash $archiveName" | Out-File -FilePath "dist/$archiveName.sha256" -Encoding ASCII -NoNewline
233+
Write-Host "Generated checksum:"
234+
Get-Content "dist/$archiveName.sha256"
235+
shell: pwsh
236+
212237
- name: Upload build artifacts
213238
uses: actions/upload-artifact@v4
214239
with:
215240
name: build-${{ matrix.asset_name_suffix }}
216-
path: dist/dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}
241+
path: |
242+
dist/dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}
243+
dist/dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}.sha256
217244
retention-days: 1
218245

219246
- name: Upload install scripts (linux-amd64 only)
@@ -274,10 +301,15 @@ jobs:
274301
tag_name: v${{ github.event.inputs.version }}
275302
files: |
276303
artifacts/build-linux-amd64/dtvem-${{ github.event.inputs.version }}-linux-amd64.tar.gz
304+
artifacts/build-linux-amd64/dtvem-${{ github.event.inputs.version }}-linux-amd64.tar.gz.sha256
277305
artifacts/build-macos-amd64/dtvem-${{ github.event.inputs.version }}-macos-amd64.tar.gz
306+
artifacts/build-macos-amd64/dtvem-${{ github.event.inputs.version }}-macos-amd64.tar.gz.sha256
278307
artifacts/build-macos-arm64/dtvem-${{ github.event.inputs.version }}-macos-arm64.tar.gz
308+
artifacts/build-macos-arm64/dtvem-${{ github.event.inputs.version }}-macos-arm64.tar.gz.sha256
279309
artifacts/build-windows-amd64/dtvem-${{ github.event.inputs.version }}-windows-amd64.zip
310+
artifacts/build-windows-amd64/dtvem-${{ github.event.inputs.version }}-windows-amd64.zip.sha256
280311
artifacts/build-windows-arm64/dtvem-${{ github.event.inputs.version }}-windows-arm64.zip
312+
artifacts/build-windows-arm64/dtvem-${{ github.event.inputs.version }}-windows-arm64.zip.sha256
281313
install.sh
282314
install.ps1
283315
body: |
@@ -314,7 +346,8 @@ jobs:
314346
315347
## Checksums
316348
317-
See the assets below for SHA256 checksums.
349+
SHA256 checksums are provided for each archive (`.sha256` files).
350+
The installers automatically verify checksums before extraction.
318351
draft: false
319352
prerelease: false
320353
generate_release_notes: true # GitHub will auto-generate additional notes

.github/workflows/script-lint.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ jobs:
4040
shell: pwsh
4141
run: |
4242
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser
43-
$results = Invoke-ScriptAnalyzer -Path ./install.ps1 -Severity Error,Warning
43+
# Exclude PSAvoidUsingWriteHost - Write-Host is intentional for colored installer output
44+
$results = Invoke-ScriptAnalyzer -Path ./install.ps1 -Severity Error,Warning -ExcludeRule PSAvoidUsingWriteHost,PSUseBOMForUnicodeEncodedFile
4445
if ($results) {
4546
$results | Format-Table -AutoSize
4647
exit 1

install.ps1

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,34 @@ function Get-LatestVersion {
4646
}
4747
}
4848

49+
function Test-Checksum {
50+
param(
51+
[string]$FilePath,
52+
[string]$ChecksumPath
53+
)
54+
55+
if (-not (Test-Path $ChecksumPath)) {
56+
Write-Error-Custom "Checksum file not found: $ChecksumPath"
57+
return $false
58+
}
59+
60+
# Read expected hash from checksum file (format: "hash filename")
61+
$checksumContent = Get-Content $ChecksumPath -Raw
62+
$expectedHash = ($checksumContent -split '\s+')[0].ToLower()
63+
64+
# Calculate actual hash
65+
$actualHash = (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash.ToLower()
66+
67+
if ($expectedHash -ne $actualHash) {
68+
Write-Error-Custom "Checksum verification failed!"
69+
Write-Error-Custom "Expected: $expectedHash"
70+
Write-Error-Custom "Actual: $actualHash"
71+
return $false
72+
}
73+
74+
return $true
75+
}
76+
4977
function Main {
5078
Write-Host ""
5179
Write-Host "========================================" -ForegroundColor Blue
@@ -105,6 +133,27 @@ function Main {
105133
exit 1
106134
}
107135

136+
# Download and verify checksum
137+
$CHECKSUM_URL = "$DOWNLOAD_URL.sha256"
138+
$CHECKSUM_PATH = Join-Path $TMP_DIR "$ARCHIVE_NAME.sha256"
139+
140+
Write-Info "Downloading checksum..."
141+
try {
142+
Invoke-WebRequest -Uri $CHECKSUM_URL -OutFile $CHECKSUM_PATH -UseBasicParsing
143+
}
144+
catch {
145+
Write-Error-Custom "Failed to download checksum file: $_"
146+
Write-Error-Custom "URL: $CHECKSUM_URL"
147+
exit 1
148+
}
149+
150+
Write-Info "Verifying checksum..."
151+
if (-not (Test-Checksum -FilePath $ARCHIVE_PATH -ChecksumPath $CHECKSUM_PATH)) {
152+
Write-Error-Custom "Archive integrity check failed - aborting installation"
153+
exit 1
154+
}
155+
Write-Success "Checksum verified"
156+
108157
# Extract archive
109158
Write-Info "Extracting archive..."
110159
Expand-Archive -Path $ARCHIVE_PATH -DestinationPath $TMP_DIR -Force

install.sh

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,41 @@ download() {
9292
fi
9393
}
9494

95+
# Verify SHA256 checksum
96+
verify_checksum() {
97+
local file=$1
98+
local checksum_file=$2
99+
100+
if [ ! -f "$checksum_file" ]; then
101+
error "Checksum file not found: $checksum_file"
102+
return 1
103+
fi
104+
105+
# Extract expected hash from checksum file (format: "hash filename")
106+
local expected_hash
107+
expected_hash=$(awk '{print $1}' "$checksum_file")
108+
109+
# Calculate actual hash
110+
local actual_hash
111+
if command -v sha256sum &> /dev/null; then
112+
actual_hash=$(sha256sum "$file" | awk '{print $1}')
113+
elif command -v shasum &> /dev/null; then
114+
actual_hash=$(shasum -a 256 "$file" | awk '{print $1}')
115+
else
116+
warning "Neither sha256sum nor shasum found - skipping checksum verification"
117+
return 0
118+
fi
119+
120+
if [ "$expected_hash" != "$actual_hash" ]; then
121+
error "Checksum verification failed!"
122+
error "Expected: $expected_hash"
123+
error "Actual: $actual_hash"
124+
return 1
125+
fi
126+
127+
return 0
128+
}
129+
95130
main() {
96131
echo ""
97132
echo -e "${BLUE}========================================${NC}"
@@ -138,7 +173,7 @@ main() {
138173

139174
# Create temporary directory
140175
TMP_DIR=$(mktemp -d)
141-
trap "rm -rf $TMP_DIR" EXIT
176+
trap 'rm -rf $TMP_DIR' EXIT
142177

143178
# Download archive
144179
info "Downloading dtvem..."
@@ -152,6 +187,24 @@ main() {
152187

153188
success "Downloaded successfully"
154189

190+
# Download and verify checksum
191+
CHECKSUM_URL="${DOWNLOAD_URL}.sha256"
192+
CHECKSUM_PATH="$TMP_DIR/${ARCHIVE_NAME}.sha256"
193+
194+
info "Downloading checksum..."
195+
if ! download "$CHECKSUM_URL" "$CHECKSUM_PATH"; then
196+
error "Failed to download checksum file"
197+
error "URL: $CHECKSUM_URL"
198+
exit 1
199+
fi
200+
201+
info "Verifying checksum..."
202+
if ! verify_checksum "$ARCHIVE_PATH" "$CHECKSUM_PATH"; then
203+
error "Archive integrity check failed - aborting installation"
204+
exit 1
205+
fi
206+
success "Checksum verified"
207+
155208
# Extract archive
156209
info "Extracting archive..."
157210
tar -xzf "$ARCHIVE_PATH" -C "$TMP_DIR"
@@ -213,9 +266,11 @@ main() {
213266
if [ -n "$SHELL_CONFIG" ]; then
214267
# Check if already in config
215268
if ! grep -q "$INSTALL_DIR" "$SHELL_CONFIG" 2>/dev/null; then
216-
echo "" >> "$SHELL_CONFIG"
217-
echo "# Added by dtvem installer" >> "$SHELL_CONFIG"
218-
echo "$EXPORT_CMD" >> "$SHELL_CONFIG"
269+
{
270+
echo ""
271+
echo "# Added by dtvem installer"
272+
echo "$EXPORT_CMD"
273+
} >> "$SHELL_CONFIG"
219274
success "Added to $SHELL_CONFIG"
220275
else
221276
info "Already in $SHELL_CONFIG"

0 commit comments

Comments
 (0)