From 0145127a05d528d46187c962a7fadadfa172fcef Mon Sep 17 00:00:00 2001 From: Leo Di Donato <120051+leodido@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:33:16 +0000 Subject: [PATCH] Fix non-deterministic gzip compression Gzip includes timestamps by default, making compression non-deterministic. This causes SLSA attestation verification failures when artifacts are re-compressed or re-uploaded, as the digest changes even with identical content. Changes: - Add -n flag to gzip commands to exclude timestamps - Add -n flag to pigz commands for parallel compression - Update getCompressionCommand to use -n with custom compression levels This ensures: - Deterministic builds (same content = same digest) - SLSA attestations remain valid across re-uploads - Reproducible builds align with SLSA best practices Fixes digest mismatch issues in sign-cache workflow where artifacts may be re-uploaded after attestation creation. Co-authored-by: Ona --- pkg/leeway/compression.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/leeway/compression.go b/pkg/leeway/compression.go index 01929f4a..6e3c330f 100644 --- a/pkg/leeway/compression.go +++ b/pkg/leeway/compression.go @@ -9,7 +9,7 @@ import ( ) var ( - compressor = "gzip" + compressor = "gzip -n" decompressor = "gzip -d" // Number of CPU cores for parallel processing cpuCores = runtime.NumCPU() @@ -20,7 +20,8 @@ func init() { pigz, err := exec.LookPath("pigz") if err == nil { // Use all available CPU cores by default - compressor = fmt.Sprintf("%s -p %d", pigz, cpuCores) + // -n flag ensures deterministic output by not storing timestamps + compressor = fmt.Sprintf("%s -n -p %d", pigz, cpuCores) } } @@ -128,7 +129,8 @@ func getCompressionCommand(algo CompressionAlgorithm, level int) string { return "" default: // Gzip or fallback if level > 0 { - return fmt.Sprintf("gzip -%d", level) + // -n flag ensures deterministic output by not storing timestamps + return fmt.Sprintf("gzip -n -%d", level) } return compressor }