From 6130b846792ad21136e7c50ae486a1f3f4047b57 Mon Sep 17 00:00:00 2001 From: Tony Lee Date: Wed, 28 Oct 2026 00:08:20 +0800 Subject: [PATCH 1/3] fix(deps): bump zip 2.4.2 -> 9.1.2 for zip2 CVEs zip <= 9.0.4 is affected by CVE-2026-115905/-115907/-115908/-115909. Only the pre-seed feature uses zip; call sites compile unchanged. Closes #1579 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01B3XpFuLNuKJRyvvTT35Mka --- Cargo.lock | 53 ++++++++++++++--------------------- crates/openab-core/Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4045d23b..c592f900d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,15 +113,6 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" -dependencies = [ - "derive_arbitrary", -] - [[package]] name = "arc-swap" version = "1.9.1" @@ -1086,12 +1077,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - [[package]] name = "crypto-bigint" version = "0.5.5" @@ -1190,17 +1175,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "derive_arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.118", -] - [[package]] name = "digest" version = "0.10.7" @@ -1382,6 +1356,7 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -1565,9 +1540,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", "rand_core 0.10.1", + "wasm-bindgen", ] [[package]] @@ -4447,6 +4424,12 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "typed-path" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e" + [[package]] name = "typemap_rev" version = "0.3.0" @@ -5178,21 +5161,27 @@ dependencies = [ [[package]] name = "zip" -version = "2.4.2" +version = "9.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" +checksum = "ec2e3161de27091f18a831d9494e9c53378a34833af5c1dda35ad85849da18d6" dependencies = [ - "arbitrary", "crc32fast", - "crossbeam-utils", - "displaydoc", "flate2", + "getrandom 0.4.3", "indexmap", "memchr", - "thiserror 2.0.18", + "nix", + "typed-path", + "windows-sys 0.61.2", "zopfli", ] +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + [[package]] name = "zmij" version = "1.0.21" diff --git a/crates/openab-core/Cargo.toml b/crates/openab-core/Cargo.toml index 1ede398f1..bffcdf810 100644 --- a/crates/openab-core/Cargo.toml +++ b/crates/openab-core/Cargo.toml @@ -41,7 +41,7 @@ tempfile = "3.27.0" aws-sdk-secretsmanager = { version = "1", optional = true } aws-sdk-s3 = { version = "1", optional = true } aws-config = { version = "1", optional = true } -zip = { version = "2", default-features = false, features = ["deflate"], optional = true } +zip = { version = "9.1.2", default-features = false, features = ["deflate"], optional = true } flate2 = { version = "1", optional = true } tar = { version = "0.4.45", default-features = false, optional = true } aws-sigv4 = { version = "1", optional = true } From 0d9ac3bd2c250b8ae3d36ea86fe4cddd2c8ebb7c Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Tue, 27 Oct 2026 12:52:24 -0400 Subject: [PATCH 2/3] fix(pre-seed): keep miniz_oxide backend and reject absolute zip entries Addresses review findings F1/F2 on the zip 2.4.2 -> 9.1.2 bump. - zip: use `deflate-flate2` instead of `deflate`. zip 9's `deflate` enables `flate2/zlib-rs`, which via feature unification switched the flate2 backend for both zip and tar.gz (`GzDecoder`) extraction from miniz_oxide to zlib-rs. `deflate-flate2` selects no backend, so the existing `flate2 = "1"` default (miniz_oxide) stays in effect. Drops `zlib-rs` and the write-only `zopfli` from the lockfile. - pre_seed: zip 9's `enclosed_name()` strips a leading `/` and accepts absolute entry names that zip 2.x rejected. Reject entries whose raw name starts with `/` or `\` so such archives keep failing closed. - test: `extract_rejects_path_traversal` covers `../`, nested `../../`, `/abs` and `\abs`, asserting rejection and that nothing is written. Verified it fails on main's zip 2.4.2 only for cases it newly pins. --- Cargo.lock | 40 +++++++------------------ crates/openab-core/Cargo.toml | 2 +- crates/openab-core/src/pre_seed.rs | 48 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c592f900d..3220f4686 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,7 +93,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -104,7 +104,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -1293,7 +1293,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1356,7 +1356,6 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", - "zlib-rs", ] [[package]] @@ -2340,7 +2339,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3355,7 +3354,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3439,7 +3438,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3880,7 +3879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3998,10 +3997,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -4728,7 +4727,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -5173,33 +5172,14 @@ dependencies = [ "nix", "typed-path", "windows-sys 0.61.2", - "zopfli", ] -[[package]] -name = "zlib-rs" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" - [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" -[[package]] -name = "zopfli" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" -dependencies = [ - "bumpalo", - "crc32fast", - "log", - "simd-adler32", -] - [[package]] name = "zune-core" version = "0.5.1" diff --git a/crates/openab-core/Cargo.toml b/crates/openab-core/Cargo.toml index bffcdf810..51aca393f 100644 --- a/crates/openab-core/Cargo.toml +++ b/crates/openab-core/Cargo.toml @@ -41,7 +41,7 @@ tempfile = "3.27.0" aws-sdk-secretsmanager = { version = "1", optional = true } aws-sdk-s3 = { version = "1", optional = true } aws-config = { version = "1", optional = true } -zip = { version = "9.1.2", default-features = false, features = ["deflate"], optional = true } +zip = { version = "9.1.2", default-features = false, features = ["deflate-flate2"], optional = true } flate2 = { version = "1", optional = true } tar = { version = "0.4.45", default-features = false, optional = true } aws-sigv4 = { version = "1", optional = true } diff --git a/crates/openab-core/src/pre_seed.rs b/crates/openab-core/src/pre_seed.rs index 2bea072c0..0f1c6ee6f 100644 --- a/crates/openab-core/src/pre_seed.rs +++ b/crates/openab-core/src/pre_seed.rs @@ -225,6 +225,12 @@ fn extract_zip_budgeted( } let mut file = archive.by_index(i)?; + // zip 9.x `enclosed_name()` strips a leading root and accepts absolute + // entry names; zip 2.x rejected them. Keep rejecting so an archive with + // absolute paths fails closed, as before the 2.x -> 9.x bump. + if matches!(file.name_raw().first(), Some(b'/' | b'\\')) { + anyhow::bail!("hooks.pre_seed: invalid zip entry name at index {i}"); + } let name = file.enclosed_name().ok_or_else(|| { anyhow::anyhow!("hooks.pre_seed: invalid zip entry name at index {i}") })?; @@ -663,6 +669,48 @@ mod tests { ); } + #[test] + fn extract_rejects_path_traversal() { + use std::io::Write; + // Pins the path-safety contract across the zip 2.x -> 9.x bump: every + // escaping or absolute entry name is rejected and nothing is written. + fn zip_with(name: &str) -> Vec { + let mut writer = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); + writer + .start_file(name, zip::write::SimpleFileOptions::default()) + .unwrap(); + writer.write_all(b"pwned").unwrap(); + writer.finish().unwrap().into_inner() + } + let deadline = Instant::now() + std::time::Duration::from_secs(60); + + for evil in [ + "../escape.txt", + "sub/../../escape.txt", + "/abs_escape.txt", + "\\abs_escape.txt", + ] { + let root = tempfile::tempdir().unwrap(); + let dest = root.path().join("dest"); + std::fs::create_dir_all(&dest).unwrap(); + + let err = extract_zip_with_limits(&zip_with(evil), &dest, deadline).unwrap_err(); + assert!( + err.to_string().contains("invalid zip entry name"), + "{evil}: expected rejection, got {err}" + ); + assert!( + !root.path().join("escape.txt").exists(), + "{evil}: escaped dest" + ); + assert_eq!( + std::fs::read_dir(&dest).unwrap().count(), + 0, + "{evil}: dest not empty" + ); + } + } + #[test] fn extract_rejects_exceeding_file_count() { use std::io::Write; From 2171842ce0ed550b8b1f158a2a5e71a3f8bc085c Mon Sep 17 00:00:00 2001 From: chaodu-agent <274062505+chaodu-agent@users.noreply.github.com> Date: Tue, 27 Oct 2026 13:02:12 -0400 Subject: [PATCH 3/3] build(deps): re-resolve Cargo.lock from main for zip 9.1.2 only Regenerate from main's lockfile with `cargo update -p zip --precise 9.1.2` so the diff touches only zip and its transitive deps. The previous regeneration downgraded unrelated windows-sys / getrandom edges (F8). --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3220f4686..2e3928104 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,7 +93,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -104,7 +104,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1293,7 +1293,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2339,7 +2339,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3354,7 +3354,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3438,7 +3438,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3879,7 +3879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3997,10 +3997,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4727,7 +4727,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]]