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



GHSA-6MW6-MJ76-GRWC

Rust's Kryptonite: Violating UTF-8 Invariants in gix-date

Alon Barad
Alon Barad
Software Engineer

Feb 27, 2026·5 min read·24 visits

Executive Summary (TL;DR)

The `TimeBuf` struct in `gix-date` publicly implemented `std::io::Write`, allowing callers to write raw, invalid UTF-8 bytes into its internal buffer. When `as_str()` was called, it created a `&str` from this corrupted data, triggering Undefined Behavior (UB). Fix: Upgrade to 0.12.0, where the `Write` implementation was removed.

In the world of Rust, the `&str` type is a sacred contract: it promises, under penalty of undefined behavior, that the underlying bytes are valid UTF-8. CVE-2026-0810 is a story of how `gix-date`, a core component of the `gitoxide` project, broke that promise by being too generous with its API surface. By implementing `std::io::Write` for a structure intended to hold a string, the developers inadvertently allowed arbitrary raw bytes—including invalid UTF-8—to be injected into a buffer that was later cast to a string slice. This violation of Rust's safety guarantees turns a simple formatting utility into a potential memory corruption vector.

The Hook: The Sacred Contract of &str

Rust is famous for its paranoia. It treats memory access like a bomb diffusal operation, forcing you to prove safety before it lets you cut the red wire. One of the most fundamental invariants in the language is the &str type. Unlike C's char* or C++'s std::string, a Rust string slice isn't just a bag of bytes; it is mathematically guaranteed to be valid UTF-8. The compiler optimizes code assuming this is true. Standard library functions rely on it. If you manage to create a &str that points to garbage non-UTF-8 data, you haven't just created a bug—you've entered the realm of Undefined Behavior (UB).

Enter gix-date, a library responsible for parsing and formatting time in gitoxide, the pure-Rust implementation of Git. Time parsing sounds boring, right? It's just numbers and colons. But gix-date needed a buffer to format these dates into strings. They created TimeBuf.

The problem wasn't what TimeBuf did; it was what it allowed others to do. In an effort to be ergonomic (or perhaps just standard-compliant), the developers implemented a trait that essentially unlocked the back door to the memory safe house and left the keys in the ignition.

The Flaw: A Trait Too Far

The vulnerability lies in a classic case of API over-exposure. The TimeBuf struct wraps a byte buffer (Vec<u8> or similar). To make it easy to write data into this buffer, the developers implemented std::io::Write for TimeBuf.

impl std::io::Write for TimeBuf {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.buf.write(buf)
    }
    // ...
}

This looks innocent. Write is a standard trait. However, TimeBuf also had a method called as_str(). This method returns a &str. For that to be safe, the internal buffer must contain valid UTF-8.

By implementing Write publicly, the library effectively said: "Hey, anyone with a mutable reference to this object can write whatever bytes they want." This bypasses any validation logic the library might have had. An attacker (or just a clumsy developer) could use the Write trait to inject 0xFF (an invalid UTF-8 byte) into the buffer. The buffer accepts it happily because Write deals in bytes, not strings. But the moment someone calls as_str(), the code performs a cast that assumes the data is valid. The invariant is broken, and the compiler's assumptions are shattered.

The Code: Breaking the Rules

Let's look at the smoking gun. The code below shows the vulnerability in its simplest form. It’s not a complex buffer overflow or a heap groom; it’s a type confusion induced by bad API design.

The Vulnerable Pattern

use gix_date::parse::TimeBuf;
use std::io::Write;
 
fn main() {
    let mut buf = TimeBuf::default();
    
    // 1. The Trojan Horse: Write trait allows arbitrary bytes
    // 0xff is NOT valid UTF-8.
    buf.write(&[0xff]).unwrap(); 
    
    // 2. The Trigger: Interpreting garbage as a string
    // This likely uses std::str::from_utf8_unchecked internally or essentially equivalent logic
    // creating a `&str` that violates the language spec.
    let s = buf.as_str(); 
    
    // 3. The UB: Using the malformed string
    println!("This is undefined behavior: {}", s);
}

When buf.as_str() is called, it returns a slice pointing to [0xff]. If the program tries to iterate over the characters of this string, search it, or print it, the underlying UTF-8 decoder will likely panic, or worse, read past the bounds if the length calculation was optimized based on UTF-8 assumptions. In Rust, UB means "anything can happen," including remote code execution if the stars align.

The Impact: Why Panic is the Best Case Scenario

You might be thinking, "So it crashes. Big deal." In the context of a library like gitoxide, which is designed to process git repositories (often untrusted ones), stability is paramount. But UB is worse than a crash.

When the compiler sees code that operates on a &str, it often elides bounds checks or makes optimization decisions based on the assumption that the data is valid UTF-8. For example, if you iterate over a &str, the iterator knows it can't land in the middle of a multibyte sequence. If you feed it invalid data, that iterator might skip the null terminator or jump into unmapped memory.

In a security context, if gix-date is used in a server-side component processing git objects, an attacker could craft a payload that triggers this UB. Best case: they DoS your server. Worst case: they exploit the memory corruption to bypass logic checks. While CVSS 7.1 suggests "High" severity, the specific impact depends heavily on how the consuming application handles the resulting malformed string.

The Fix: Revoking Write Access

The fix provided by the Gitoxide team in commit 76376ef5e97c63e108db0c9fe2eb096f4bfe70f7 is elegantly simple: they removed the feature.

The Patch

// gix-date/src/parse/mod.rs
 
// DELETED:
// impl std::io::Write for TimeBuf { ... }
 
// MODIFIED:
impl Time {
    pub fn to_str<'a>(&self, buf: &'a mut TimeBuf) -> &'a str {
        buf.clear();
        // Instead of writing to 'buf' via the trait, they access the internal buffer directly
        // inside the module, where they can guarantee the output is valid ASCII/UTF-8.
        self.write_to(&mut buf.buf)
            .expect("write to memory of just the right size cannot fail");
        buf.as_str()
    }
}

By removing impl Write for TimeBuf, the developers enforced encapsulation. Now, the only way to get data into TimeBuf is through specific methods provided by the library (like Time::to_str), which are written to ensure they only produce valid text. The internal buffer (buf.buf) is no longer exposed to the chaotic whims of the outside world via a generic trait.

Official Patches

GitoxideLabsPull Request removing the vulnerable trait implementation

Fix Analysis (1)

Technical Appendix

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

Affected Systems

gix-date < 0.12.0gitoxide < 0.12.0Red Hat Enterprise Linux 8Red Hat Enterprise Linux 9Red Hat Enterprise Linux 10

Affected Versions Detail

Product
Affected Versions
Fixed Version
gix-date
GitoxideLabs
< 0.12.00.12.0
gitoxide
GitoxideLabs
< 0.12.00.12.0
AttributeDetail
CWECWE-135 (Incorrect Calculation of Multi-Byte String Length)
CVSS v3.17.1 (High)
VectorAV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H
EPSS Score0.00004 (Low Probability)
Attack VectorLocal / Library API Misuse
Patch Commit76376ef5e97c63e108db0c9fe2eb096f4bfe70f7

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1203Exploitation for Client Execution
Execution
CWE-135
Incorrect Calculation of Multi-Byte String Length

The application does not correctly calculate the length of a multi-byte string, leading to potential memory corruption or undefined behavior.

Known Exploits & Detection

GitHub Issue #2305PoC demonstrating panic via invalid UTF-8 injection in TimeBuf

Vulnerability Timeline

Vulnerability reported via GitHub Issue
2025-12-27
Fix merged into main branch
2025-12-31
RustSec Advisory published
2026-01-04
CVE Assigned
2026-01-26

References & Sources

  • [1]RUSTSEC-2025-0140 Advisory
  • [2]NVD CVE-2026-0810
Related Vulnerabilities
CVE-2026-0810

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

•43 minutes ago•CVE-2026-115906
6.5

CVE-2026-115906: AES Entry HMAC Authentication Bypass in Rust zip Crate

CVE-2026-115906 is a cryptographic authentication bypass vulnerability in the Rust zip library (zip-rs/zip2) affecting versions from 0.6.0 prior to 9.0.0. In the WinZip AE-x AES decryption reader implementation within src/aes.rs, the HMAC-SHA1-80 authentication tag is only validated when the internal byte counter (data_remaining) decrements to exactly zero. Because this counter is initialized from the unauthenticated compressed_size header field, an attacker can craft a ZIP archive where the entry stream hits premature physical end-of-file (EOF) before data_remaining reaches zero, causing the reader to return Ok(0) and skip HMAC verification entirely.

Alon Barad
Alon Barad
1 views•13 min read
•about 2 hours 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 3 hours ago•CVE-2026-115907
7.5

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

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.

Alon Barad
Alon Barad
2 views•12 min read
•about 4 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 5 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 6 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