From 1c2d155fcc0a11e0a69c95fa6895c013dd147e0f Mon Sep 17 00:00:00 2001 From: Julian lechner Date: Fri, 11 Sep 2026 16:07:17 +0200 Subject: [PATCH] fix(installer): write manifest hashes lowercase and without a BOM (PowerShell) Windows PowerShell 5.1's -Encoding UTF8 always prepends a BOM, and Get-FileHash returns uppercase hex. Bash's manifest reader expects neither, so a manifest written by this module and later read by the Bash equivalent (or vice versa) mismatched on every single entry: the BOM folded into the header's first field, and every hash comparison failed on case alone. Hashes are now lowercased on read and write, and the manifest file itself is written UTF-8 without a BOM. Co-Authored-By: Claude Sonnet 5 --- scripts/lib/manifest.ps1 | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/scripts/lib/manifest.ps1 b/scripts/lib/manifest.ps1 index d6cd06e..d0d4d46 100644 --- a/scripts/lib/manifest.ps1 +++ b/scripts/lib/manifest.ps1 @@ -5,13 +5,15 @@ function Get-ManagedManifestPath { function Get-Sha256Hash { param([Parameter(Mandatory=$true)][string]$Path) - return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash + # Lowercase to match sha256sum's output, since the manifest must be readable by + # both this module and its Bash equivalent regardless of which one wrote it. + return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant() } function Get-Sha256HashOfBytes { param([Parameter(Mandatory=$true)][byte[]]$Bytes) $sha256 = [System.Security.Cryptography.SHA256]::Create() - try { return ([System.BitConverter]::ToString($sha256.ComputeHash($Bytes))).Replace('-', '') } + try { return ([System.BitConverter]::ToString($sha256.ComputeHash($Bytes))).Replace('-', '').ToLowerInvariant() } finally { $sha256.Dispose() } } @@ -19,7 +21,8 @@ function Read-ManagedManifest { param([Parameter(Mandatory=$true)][string]$ManifestPath) $entries = @{} if (Test-Path -LiteralPath $ManifestPath) { - Import-Csv -LiteralPath $ManifestPath -Delimiter ([char]9) | ForEach-Object { $entries[$_.path] = $_.sha256 } + # Lowercase to tolerate an older manifest written before hashes were normalized. + Import-Csv -LiteralPath $ManifestPath -Delimiter ([char]9) | ForEach-Object { $entries[$_.path] = $_.sha256.ToLowerInvariant() } } return $entries } @@ -29,7 +32,12 @@ function Write-ManagedManifest { $lines = @("path`tsha256") foreach ($path in ($Entries.Keys | Sort-Object)) { $lines += "$path`t$($Entries[$path])" } New-Item (Split-Path $ManifestPath -Parent) -ItemType Directory -Force | Out-Null - Set-Content -LiteralPath $ManifestPath -Value $lines -Encoding UTF8 + # Windows PowerShell 5.1's -Encoding UTF8 always prepends a BOM, which Bash's plain + # `read` would otherwise fold into the first field of the header line. Write UTF-8 + # without BOM and with LF line endings so either implementation can read the file + # regardless of which one wrote it. + $content = ($lines -join "`n") + "`n" + [System.IO.File]::WriteAllText($ManifestPath, $content, (New-Object System.Text.UTF8Encoding($false))) } function Sync-ManagedDestination {