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
7.10.00%

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

Alon Barad
Alon Barad
Software Engineer

Feb 27, 2026·5 min read·6 visits

PoC Available

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.