diff --git a/crates/ecrou/src/download.rs b/crates/ecrou/src/download.rs index abecf07..8d99817 100644 --- a/crates/ecrou/src/download.rs +++ b/crates/ecrou/src/download.rs @@ -113,6 +113,14 @@ pub fn download_image( if !url.starts_with("http://") && !url.starts_with("https://") { return Err(anyhow!("Unsupported URL scheme: {}", url).into()); } + if url.ends_with(".tar.bz2") || url.ends_with(".tbz2") { + return Err(anyhow!( + "bzip2-compressed tarballs are not supported: {} (use a \ + .tar.gz, .tar.xz or .tar.zst source)", + url + ) + .into()); + } // Verify the tarball against the checksum the distro publishes // next to it. A fetch failure (missing artifact, network error) // degrades to an unverified download with a warning rather than diff --git a/crates/ecrou/src/extract.rs b/crates/ecrou/src/extract.rs index 3a964d7..220866c 100644 --- a/crates/ecrou/src/extract.rs +++ b/crates/ecrou/src/extract.rs @@ -45,6 +45,14 @@ fn extract_single_archive( extract_xz(reader, dest, &mut fixups, progress)?; } else if filename.ends_with(".tar.zst") || filename.ends_with(".tar.zstd") { extract_zst(reader, dest, &mut fixups, progress)?; + } else if filename.ends_with(".tar.bz2") || filename.ends_with(".tbz2") { + // Named before the magic-byte fallback misreads a bzip2 + // stream as an uncompressed tar. + return Err(anyhow::anyhow!( + "bzip2-compressed tarballs are not supported: {} (use a \ + .tar.gz, .tar.xz or .tar.zst rootfs)", + tarball.display() + )); } else if filename.ends_with(".tar") { extract_tar(reader, dest, &mut fixups, progress)?; } else { @@ -802,4 +810,19 @@ mod tests { Path::new("etc/dir/absent.pem") ); } + #[test] + fn a_bzip2_tarball_is_a_named_error() { + let dir = tempfile::tempdir().unwrap(); + let tarball = dir.path().join("rootfs.tar.bz2"); + std::fs::write(&tarball, b"BZh9-not-really").unwrap(); + let out = tempfile::tempdir().unwrap(); + let err = format!( + "{:#}", + extract_tarball(&tarball, out.path(), &NoProgress).unwrap_err() + ); + assert!( + err.contains("bzip2-compressed tarballs are not supported"), + "{err}" + ); + } }