Feb 28, 2026·6 min read·27 visits
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.
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.
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).
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
}
}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(())
}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.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
hivex 1millibyte | = 0.2.0 | 0.2.1 |
| Attribute | Detail |
|---|---|
| Vulnerability ID | GHSA-J8CJ-HW74-64JV |
| CWE IDs | CWE-415 (Double Free), CWE-416 (Use After Free) |
| CVSS (Est.) | 8.1 (High) |
| Platform | Rust / crates.io |
| Attack Vector | Local / Context Dependent |
| Patch Status | Fixed in v0.2.1 |
Double Free
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.