May 15, 2026·5 min read·13 visits
A panic safety bug in rkyv's `InlineVec::clear` and `SerVec::clear` methods leads to Use-After-Free and Double Free conditions if element destructors panic. Upgrading to 0.8.16 resolves the issue by updating container state before initiating destructors.
The rkyv zero-copy deserialization framework for Rust suffers from a panic safety vulnerability in its manual memory management logic. The flaw allows memory corruption, specifically Double Free and Use-After-Free, when element destructors panic during vector clearance.
The rkyv library is a zero-copy deserialization framework for Rust. It provides custom vector implementations, specifically InlineVec and SerVec, to manage memory during serialization and deserialization processes. These collections handle memory allocations and deallocations manually to optimize performance.
A vulnerability tracked as GHSA-VFVV-C25P-M7MM and RUSTSEC-2026-0122 exists in the memory management logic of these custom collections. The issue stems from a lack of panic safety during the execution of element destructors. The vulnerability affects rkyv versions strictly greater than or equal to 0.8.0 and less than 0.8.16.
When an element's Drop implementation panics during a call to the clear method, the container's internal length field remains unaltered. This discrepancy between the logical state and the physical memory state leads to undefined behavior. The vulnerability exposes applications to memory corruption risks, primarily Use-After-Free and Double Free conditions.
The root cause lies in the sequencing of operations within the InlineVec::clear and SerVec::clear functions. These functions are responsible for deallocating the objects held within the collections by iterating over them and invoking drop_in_place. This function runs the destructors for the allocated memory regions.
In the vulnerable design, the collections wait for the iteration loop to complete successfully before resetting their internal len fields to zero. This approach assumes that destructors will never panic, which violates strict Rust panic safety guarantees. The length update is executed as the final step of the function block.
If a panic occurs while processing an element, normal control flow is interrupted by unwinding. The loop terminates prematurely, and the function's final length assignment is bypassed entirely. The container exits the function execution prematurely but maintains its previous state.
Because the length field is not decremented, the collection struct retains logical ownership over the entire original array of objects. Elements that were successfully destroyed prior to the panic are still considered active members of the vector, leading to dangling pointers within the container's accessible range.
The flawed logic is visible in the vulnerable implementation of the clear method. The function iterates through the allocated elements and drops them sequentially. The critical length update is positioned at the very end of the function body, leaving a window for panic unwinding to bypass the state update.
// VULNERABLE CODE (Simplified)
pub fn clear(&mut self) {
for i in 0..self.len {
unsafe {
self.elements[i].as_mut_ptr().drop_in_place();
}
}
// State is updated AFTER the potentially panicking loop
self.len = 0;
}The fix implemented in commit 5828cf5c27b664eb4432c4a93d4769e12e5e42fb adopts the "Commit Before Side-Effect" design pattern. The length field is stored locally and immediately zeroed out before any destructors are invoked. This ensures the container reflects an empty state prior to executing arbitrary Drop code.
// PATCHED CODE (Simplified)
pub fn clear(&mut self) {
let len = self.len;
// State is committed BEFORE the side-effect operations
self.len = 0;
for i in 0..len {
unsafe {
self.elements[i].as_mut_ptr().drop_in_place();
}
}
}By separating the state update from the side-effecting operations, the function ensures the collection remains consistent even during unwinding. Any subsequent attempts to access or drop the vector will perceive it as empty, completely mitigating the double-free condition.
Exploitation requires a specific program state where an attacker controls the data types being managed by rkyv or can intentionally trigger a panic within a custom Drop implementation. The vulnerability triggers undefined behavior via two primary mechanisms during the unwinding phase. Both mechanisms require the application to process complex types with panicking destructors.
The first mechanism is a Double Free condition (CWE-415). If the unwinding process subsequently drops the InlineVec or SerVec container itself, the container's destructor will re-iterate over the full length of the vector. The unmodified length field directs the program to drop the entire collection array again.
During this second iteration, the system re-invokes destructors on the memory regions that were already freed before the initial panic occurred. This double invocation results in heap corruption that can crash the application or facilitate arbitrary code execution depending on the underlying allocator.
The second mechanism is a Use-After-Free condition (CWE-416). This occurs if the application catches the panic using the std::panic::catch_unwind facility and resumes standard execution. The program regains access to the original vector, whose length field falsely advertises the presence of valid elements. Accessing elements at the lower indices references the deallocated memory.
The maintainers resolved the vulnerability in rkyv version 0.8.16. Organizations utilizing this crate must upgrade their dependencies to incorporate the panic-safe memory management logic. Updating the package strictly removes the flaw without requiring architectural changes to consumer applications.
Software engineers developing custom memory allocators or containers in Rust must adhere strictly to panic safety principles. State changes that govern memory ownership must be finalized before invoking user-controlled code. This "Commit Before Side-Effect" pattern is mandatory for safe unsafe-code encapsulation.
Developers should review custom implementations of functions like clear, truncate, and pop. The internal length and capacity fields must accurately reflect the memory state prior to executing drop_in_place. Manual drops inside a loop require extreme caution regarding how unwinding behaves at each step.
To detect similar flaws, security teams can leverage dynamic analysis tools such as Miri. Executing test suites with Miri enabled and intentionally introducing panicking destructors will rapidly expose inconsistent memory states and dangling pointers.
| Product | Affected Versions | Fixed Version |
|---|---|---|
rkyv rkyv developers | >= 0.8.0, < 0.8.16 | 0.8.16 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-415 / CWE-416 |
| Attack Vector | Local / Application-Level |
| Impact | Memory Corruption / Denial of Service |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
| CVSS | High (Unscored) |
CVE-2024-29203 identifies a cross-site scripting (XSS) vulnerability in the content ingestion and parsing mechanics of TinyMCE rich text editor. Due to a failure to enforce sandbox attributes on dynamic iframe elements and safely handle legacy embed objects, unauthenticated attackers can inject malicious elements that execute scripts within the context of the parent application session.
A technical breakdown of the OS command injection vulnerability in the shell-quote NPM package (CVE-2026-9277 / GHSA-w7jw-789q-3m8p). The bug resides in the character-by-character backslash-escaping logic applied to the .op field of object-tokens within the quote() function, which fails to match and escape line terminators due to a regex matching oversight in JavaScript. This allows unauthenticated remote attackers to execute arbitrary shell commands if they can control inputs processed by this library.
A high-severity memory corruption vulnerability exists in the V8 JavaScript engine of Google Chrome before versions 149.0.7827.102/103. The flaw arises from an incorrect bounds-check elimination during JIT compilation by the TurboFan optimizer, allowing remote attackers to achieve out-of-bounds read and write access inside the sandboxed renderer process.
An improper authentication vulnerability (CWE-287) exists in the legacy, deprecated Internet Key Exchange version 1 (IKEv1) key exchange protocol implementation in Check Point Security Gateways. The vulnerability is caused by a logic flow weakness during the certificate validation process for Remote Access VPN and Mobile Access (SSL VPN) connections. An unauthenticated remote attacker can exploit this weakness to bypass user authentication entirely, establishing a fully functional Remote Access VPN connection without a valid password.
GeoNode versions prior to 4.4.5 and 5.0.2 are vulnerable to Server-Side Request Forgery (SSRF) in the service registration endpoint. Authenticated attackers with low privileges can exploit insufficient input validation in the Web Map Service (WMS) registration module to force the application server to make outbound network queries to loopback addresses, private RFC1918 subnets, link-local scopes, and cloud metadata endpoints. This technical report details the mechanics of the vulnerability, the underlying architectural flaw, and how to effectively remediate and mitigate the associated security risks.
CVE-2022-0492 is a high-severity missing authorization vulnerability in the Linux kernel's Control Groups (cgroups) v1 implementation. The flaw resides within the cgroup_release_agent_write function in kernel/cgroup/cgroup-v1.c, where the kernel fails to validate if the process writing to the release_agent file possesses administrative capabilities in the initial user namespace. This allows a local attacker inside a container with root privileges (UID 0) to abuse user namespaces, mount a cgroups v1 directory, modify the release_agent parameter, and execute arbitrary commands on the host system as host root, effectively achieving a complete container escape.