CVE-2026-115909: Unbounded Symlink-Target Allocation Causes Process Abort in Rust zip Crate
Vulnerability ID: CVE-2026-115909
CVSS Score: 7.5
Published: 2026-10-29
A vulnerability in the Rust zip crate (versions 1.3.0 prior to 9.0.0) allows an attacker to trigger an uncatchable process abort via a crafted ZIP archive. When extracting symbolic link entries on Unix or Windows targets, ZipArchive::extract passes the untrusted, attacker-controlled uncompressed_size header value directly to Vec::with_capacity before reading or validating entry payload data. By supplying a 112-byte archive with a ZIP64 extended information field declaring an excessive uncompressed size, an attacker forces the memory allocator to fail and invoke handle_alloc_error(), immediately terminating the entire process with SIGABRT.
TL;DR
Versions 1.3.0 to < 9.0.0 of the Rust zip crate trust the uncompressed_size field in ZIP headers when pre-allocating memory for symbolic link targets during extraction. A 112-byte malicious ZIP archive can request exabytes of memory via Vec::with_capacity, triggering an uncatchable OS-level SIGABRT that bypasses std::panic::catch_unwind and thread isolation. Upgrade to zip version 9.0.0 to enforce a 4,096-byte upper bound on symlink targets.
⚠️ Exploit Status: POC
Technical Details
- Vulnerability Class: CWE-789 (Memory Allocation with Excessive Size Value) / CWE-400
-
Affected Component: Rust
zipcrate (ZipArchive::extractinsrc/read/mod.rs) - Affected Versions: >= 1.3.0, < 9.0.0
- Patched Version: 9.0.0
- CVSS v3.1 Score: 7.5 HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
- EPSS Score: 0.461% (39.91th percentile)
-
Primary Impact: Uncatchable Process Abort (
SIGABRT) / Denial of Service - Exploit Status: Public PoC Available (112-byte ZIP64 archive)
Affected Systems
- Rust applications using the
zipcrate (versions >= 1.3.0, < 9.0.0) on Unix or Windows targets - Archive extraction services and CLI tools invoking
ZipArchive::extractorZipStreamReaderon untrusted ZIP files -
zip (Rust crate): >= 1.3.0, < 9.0.0 (Fixed in:
9.0.0)
Code Analysis
Commit: a543a1f
Reject oversized symlink targets during extraction by enforcing MAX_SYMLINK_TARGET_LEN (4096 bytes) before calling Vec::with_capacity.
File: src/read/mod.rs
@@ -15,6 +15,14 @@ use std::io::{self, Read, Seek, Write};
use std::path::Path;
use std::sync::OnceLock;
+/// Upper bound on the uncompressed size of a symlink entry.
+///
+/// A symlink target is a filesystem path, so its length is bounded by the
+/// platform (`PATH_MAX` is 4096 on Linux) no matter what the archive says. The
+/// uncompressed size stored in the central directory is attacker-controlled,
+/// so entries above this bound are rejected rather than pre-allocated.
+pub(crate) const MAX_SYMLINK_TARGET_LEN: u64 = 4096;
+
mod config;
pub use config::{ArchiveOffset, Config};
@@ -395,7 +403,22 @@ impl<R: Read + Seek> ZipArchive<R> {
#[cfg(any(unix, windows))]
if file.is_symlink() {
- let mut target = Vec::with_capacity(file.size() as usize);
+ let declared_len = file.size();
+ if declared_len > MAX_SYMLINK_TARGET_LEN {
+ return Err(invalid!(
+ "symlink target declares {} bytes, more than the {} byte limit",
+ declared_len,
+ MAX_SYMLINK_TARGET_LEN
+ ));
+ }
+
+ let mut target = Vec::with_capacity(declared_len as usize);
file.read_to_end(&mut target)?;
drop(file);
make_symlink(&outpath, &target, &self.shared.files)?;
File: src/read/stream.rs
@@ -78,8 +79,24 @@ impl<R: Read> ZipStreamReader<R> {
if file.is_symlink() {
- let mut target = Vec::with_capacity(file.size() as usize);
+ let declared_len = file.size();
+ if declared_len > MAX_SYMLINK_TARGET_LEN {
+ return Err(invalid!(
+ "symlink target declares {} bytes, more than the {} byte limit",
+ declared_len,
+ MAX_SYMLINK_TARGET_LEN
+ ));
+ }
+
+ let mut target = Vec::with_capacity(declared_len as usize);
file.read_to_end(&mut target)?;
make_symlink(&outpath, &target, &self.1)?;
return Ok(());
Exploit Details
- GitHub Security Advisory: Official advisory containing the 112-byte Base64-encoded ZIP64 trigger archive and Rust reproduction harness.
-
GitHub Commit (Upstream Test Suite): Upstream patch commit including
extract_symlink_with_hostile_declared_sizeintests/extract_symlink.rswhich programmatically constructs the exploit archive.
Mitigation Strategies
- Upgrade the
zipcrate dependency to version 9.0.0 or later to enforce a 4,096-byte upper bound on symbolic link target allocations. - Implement a pre-extraction metadata validation loop using
ZipArchive::by_index_rawto reject any archive entry wherefile.is_symlink()is true andfile.size() > 4096before invokingZipArchive::extract. - Avoid using the high-level
ZipArchive::extractconvenience method on untrusted archives; instead, iterate entries manually, disable automatic symlink creation if not required by business logic, and read entry streams usingstd::io::Read::taketo cap memory growth. - Isolate untrusted archive extraction workloads into dedicated child processes with strict OS resource limits (
ulimit/ cgroups) so thatSIGABRTfromhandle_alloc_errorcannot terminate the primary service process.
Remediation Steps:
- Audit
Cargo.lockacross all Rust repositories to identify dependencies onzipversions>= 1.3.0and< 9.0.0(e.g., runcargo tree -i zip). - Update
Cargo.tomlto specifyzip = "9.0.0"(or latest compatible>= 9.0.0release) and runcargo update -p zip. - If locked to an older major version (e.g.,
zip7.x or 8.x), wrap all calls toZipArchive::extractwith a metadata inspection check that verifiesfile.size() <= 4096wheneverfile.is_symlink()is true. - Add regression tests using a ZIP64 symlink header with
uncompressed_size = 1 << 62to verify that the application returns an error rather than aborting.
References
- GitHub Security Advisory GHSA-q7v9-x93c-xqv3
- GitHub Pull Request #984: Reject oversized symlink targets
- Fix Commit a543a1fc8f3f3eef36f27bb137230295284cdb98
- zip v9.0.0 Release Notes
- NVD - CVE-2026-115909 Detail
- CVE.org Record: CVE-2026-115909
- CVEListV5 JSON Record for CVE-2026-115909
- GitHub Advisory Database OSV Record (GHSA-q7v9-x93c-xqv3)
Read the full report for CVE-2026-115909 on our website for more details including interactive diagrams and full exploit analysis.
Top comments (0)