CVEReports
CVEReports

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

Product

  • Home
  • Dashboard
  • 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-J8CJ-HW74-64JV
8.10.04%

Critical Unsoundness in Rust 'hivex' Crate Leading to Double-Free and Use-After-Free

Alon Barad
Alon Barad
Software Engineer

Feb 28, 2026·6 min read·5 visits

PoC Available

Executive Summary (TL;DR)

The 'hivex' crate v0.2.0 contains critical unsoundness issues. Calling the public `close()` method causes a double-free when the object goes out of scope. Additionally, the `from_handle` API allows creating multiple owners for a single C-handle, leading to Use-After-Free. Update to version 0.2.1 immediately.

A critical memory safety vulnerability exists in the `hivex` Rust crate (version 0.2.0), a binding for the Windows Registry hive extraction library. The vulnerability stems from incorrect implementation of the `Drop` trait and the exposure of raw handle creation APIs as safe functions. These implementation flaws allow safe Rust code to trigger Double-Free (CWE-415) and Use-After-Free (CWE-416) conditions. Specifically, the `close()` method frees the underlying C resource without preventing the destructor from running, and the `from_handle()` function allows the creation of multiple owning references to the same underlying pointer. Successful exploitation results in undefined behavior, memory corruption, and potential arbitrary code execution.

Vulnerability Overview

The hivex crate provides Rust bindings for the hivex C library, which is used to extract and inspect Windows Registry hive files. Rust's safety guarantees rely heavily on the ownership model and the Resource Acquisition Is Initialization (RAII) pattern, typically implemented via the Drop trait. This vulnerability represents a catastrophic failure of those guarantees within the library's safe API surface.

In version 0.2.0, the library exposed two distinct but related flaws. First, it allowed manual resource management via a close() method that conflicted with automatic resource management in Drop. Second, it allowed the creation of aliased ownership via from_handle, treating a raw pointer operation as safe.

Because these flaws are exposed in the safe public API, they are classified as 'unsound'. In the Rust ecosystem, unsoundness is considered a critical defect because it allows developers to write code that compiles and passes safety checks but results in Undefined Behavior (UB) at runtime. This undermines the core promise of the language.

Root Cause Analysis

The vulnerability is driven by two specific implementation errors regarding the management of the underlying C hive_h handle.

1. Double-Free via close() and Drop interaction: The Hive struct implements the Drop trait, which automatically calls the C function hivex_close when a Hive instance goes out of scope. However, the library also provided a public close(self) method. In version 0.2.0, this method manually called hivex_close but failed to inhibit the subsequent execution of the Drop glue. When the Hive variable consumes self in close(), the compiler still generates a call to drop() at the end of the scope (or strictly speaking, when the moved value is dropped). Since the C library does not track the validity of the handle after closure, it attempts to free the same memory address twice, causing a crash or heap corruption.

2. Unsound Aliasing via from_handle: The library exposed pub const fn from_handle(handle: *mut sys::hive_h) -> Hive. By marking this function as safe, the library asserted that passing any raw pointer to it was safe, which is incorrect. Furthermore, it allowed a developer to create multiple Hive structs from the same raw pointer. Since Hive implements Drop (ownership semantics), creating two Hive instances pointing to the same handle results in both instances attempting to free the handle when they drop. This race to free the resource leads to Double-Free or Use-After-Free (if one instance is used after the other has dropped).

Code Analysis

The following analysis highlights the flawed implementation in version 0.2.0 and the remediation in 0.2.1.

Vulnerable Code (v0.2.0) In the vulnerable version, close simply calls the C function. Rust's ownership semantics mean self is dropped at the end of the function (or the caller's scope), triggering Drop.

// Vulnerable implementation
impl Hive {
    // Incorrect: Safe function taking raw pointer
    pub const fn from_handle(handle: *mut sys::hive_h) -> Hive {
        Hive { handle }
    }
 
    pub fn close(self) -> Result<()> {
        // Calls C free()
        let ret = unsafe { sys::hivex_close(self.handle) };
        // PROBLEM: 'self' is dropped here. 
        // The Drop impl calls hivex_close(self.handle) AGAIN.
        if ret != 0 { /* handle error */ }
        Ok(())
    }
}
 
impl Drop for Hive {
    fn drop(&mut self) {
        unsafe { sys::hivex_close(self.handle); }
    }
}

Patched Code (v0.2.1) The patch introduces std::mem::forget to prevent the destructor from running after a manual close, and marks from_handle as unsafe.

// Patched implementation
impl Hive {
    // Fix 1: Marked unsafe. Caller must guarantee validity and ownership.
    pub unsafe fn from_handle(handle: *mut sys::hive_h) -> Hive {
        Hive { handle }
    }
 
    pub fn close(self) -> std::io::Result<()> {
        let status = unsafe { sys::hivex_close(self.as_handle()) };
        let result = check_status_zero(status);
        
        // Fix 2: Prevent Drop from running.
        // This tells the compiler "forget about this variable, do not run destructors".
        std::mem::forget(self);
        
        result
    }
}

Exploitation Proof-of-Concept

Because this vulnerability exists in the safe API, exploitation is trivial and can occur accidentally during normal development. No complex memory grooming is required to trigger the crash, although exploiting it for RCE would require standard heap manipulation techniques.

Scenario 1: The Manual Close (Double-Free) This represents the most common usage pattern that would trigger the bug.

fn trigger_double_free() -> anyhow::Result<()> {
    // 1. Open a valid hive file
    let hive = hivex::Hive::open("NTUSER.DAT", OpenFlags::empty())?;
    
    // 2. Manually close it to handle errors explicitly
    hive.close()?; // Handle is freed here by hivex_close
    
    // 3. End of scope
    // 'hive' is dropped. Drop calls hivex_close(handle) AGAIN.
    // Result: Double-Free abort or heap corruption.
    Ok(())
}

Scenario 2: Handle Aliasing (Use-After-Free) This demonstrates how from_handle allows violating ownership rules.

fn trigger_aliasing() -> anyhow::Result<()> {
    let hive1 = hivex::Hive::open("NTUSER.DAT", OpenFlags::empty())?;
    
    // Create a second owner of the SAME handle. This was allowed in safe code.
    let hive2 = hivex::Hive::from_handle(hive1.as_handle());
    
    // hive2 is dropped here -> frees handle.
    drop(hive2); 
    
    // hive1 is used here -> Use-After-Free
    // hive1 is dropped here -> Double-Free
    Ok(())
}

Impact Assessment

The impact of this vulnerability ranges from Denial of Service (DoS) to potential Remote Code Execution (RCE), depending on the context in which the library is used.

Denial of Service (DoS): The most immediate impact is application crashing. Modern allocators (like glibc's malloc or jemalloc) often detect double-frees and abort execution immediately to prevent exploitation. For a service processing uploaded hive files, this allows a remote attacker to crash the service reliably.

Memory Corruption & Execution: If the allocator does not detect the double-free, or if the attacker can manipulate the heap state between the first free and the second usage (in the aliasing scenario), this leads to standard Use-After-Free exploitation flows. An attacker could overwrite function pointers or manipulate object metadata, leading to arbitrary code execution with the privileges of the application.

Safety Guarantee Violation: For the Rust ecosystem, the severity is amplified by the violation of safety guarantees. Developers choose Rust to prevent exactly this class of bugs. A library that exposes UB in safe code invalidates the security model of the entire application relying on it.

Official Patches

crates.ioPatched version 0.2.1 release on crates.io

Fix Analysis (1)

Technical Appendix

CVSS Score
8.1/ 10
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Probability
0.04%

Affected Systems

Rust applications using `hivex` crate version 0.2.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
hivex
1millibyte
= 0.2.00.2.1
AttributeDetail
Vulnerability IDGHSA-J8CJ-HW74-64JV
CWE IDsCWE-415 (Double Free), CWE-416 (Use After Free)
CVSS (Est.)8.1 (High)
PlatformRust / crates.io
Attack VectorLocal / Context Dependent
Patch StatusFixed in v0.2.1

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1203Exploitation for Client Execution
Execution
CWE-415
Double Free

Double Free

Vulnerability Timeline

Vulnerability reported by researcher Tim Lange
2026-02-26
Advisory Published (RUSTSEC-2026-0029)
2026-02-27
Patch Released (hivex v0.2.1)
2026-02-27

References & Sources

  • [1]RUSTSEC-2026-0029 Advisory
  • [2]GHSA-J8CJ-HW74-64JV Advisory
  • [3]Issue Tracker Discussion

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.