Rust-Memory-Safety-Alert

Rust’s memory-safety guarantees challenged by flaws in its standard library

Cybersecurity News

Microsoft’s FORGE Lab uncovered bugs that allow safe Rust code to trigger undefined behavior, including an 11-year-old flaw and weaknesses affecting stable releases.

Rust’s reputation for preventing memory-safety vulnerabilities faces a fresh test after Microsoft researchers uncovered several flaws in the language’s standard library, including bugs that can allow programs written entirely in safe Rust to trigger undefined behavior.

The findings, disclosed by Microsoft’s FORGE Lab on November 9, highlight weaknesses in the unsafe code underlying Rust’s standard library. One issue dates back to 2015, while another has persisted since 2021. Both affect stable Rust releases.

The discoveries are significant because Rust is designed to prevent memory errors through its ownership model and type system. Unlike C and C++, the language enforces rules governing how programs access and manage memory, helping developers avoid common vulnerabilities such as buffer overflows and use-after-free errors.

However, Rust’s standard library relies on unsafe code internally to implement functionality exposed through safe application programming interfaces (APIs). If that underlying code makes incorrect assumptions about memory, concurrent operations or operating-system behavior, applications using seemingly safe functions can still encounter undefined behavior.

Microsoft’s researchers identified three recurring patterns behind the problems: unsafe code that assumes other operations will not fail, code that trusts caller-provided implementations to behave correctly, and code that makes incorrect assumptions about the underlying operating system.

An 11-year-old flaw in process termination

One of the oldest issues involves Rust’s process::exit implementation and its handling of alternate signal stacks on Unix systems.

Rust uses alternate signal stacks to handle stack-overflow conditions. When a thread exhausts its stack, the operating system delivers a signal. Rust uses a separate memory area to handle that signal and display an error message before terminating the process.

Microsoft found that when a child thread calls process::exit, Rust’s cleanup routine can unmap the alternate signal stack belonging to the main thread while that thread is still running.

If the main thread subsequently overflows its stack during the short interval before the process terminates, the operating system may attempt to deliver a signal using memory that has already been unmapped. Microsoft’s proof of concept produced a segmentation fault instead of the expected Rust stack-overflow message.

The issue dates back to 2015. Researchers also examined whether an attacker could exploit it to achieve code execution by mapping writable memory at the address of the unmapped signal stack and manipulating the signal handler’s execution.

However, Microsoft found no reliable exploitation path under the conditions it tested and assessed practical exploitation as unlikely. The proposed fix stops cleaning up the main thread’s alternate signal stack during process termination.

Another issue involves CommandExt::exec, a Unix function that replaces the current process with another program.

Microsoft found that the function modifies the process-wide environment while holding a read lock rather than an exclusive lock. This allows other threads to access the environment while it is being modified.

In certain circumstances, concurrent operations can leave the environment pointing to freed memory, potentially causing undefined behavior when another thread accesses it.

The underlying problem dates back to 2021, when Rust’s environment lock was changed to a read-write lock. Microsoft said a proposed fix that avoids modifying the environment through this mechanism was under review when it published its findings.

Safe APIs can expose unsafe behavior

A separate finding involved Rust’s str::replace function, which replaces matching patterns in strings.

The function includes an optimization for replacing individual ASCII characters. Microsoft found that the implementation incorrectly assumed a one-byte string pattern must contain an ASCII character.

However, Rust’s nightly Pattern trait allows custom implementations to provide their own pattern descriptions. A specially constructed implementation could return a non-ASCII byte, causing the replacement function to modify bytes inside a multibyte UTF-8 character.

The resulting string could contain invalid UTF-8 data despite being created through a safe API. Subsequent string operations that rely on valid UTF-8 could then trigger undefined behavior.

Microsoft reported the issue to Rust maintainers. The fix changed the internal representation of the string pattern from a byte slice to a string slice, ensuring that the type itself enforces UTF-8 validity.

The researchers also described a panic-safety issue involving the nightly MapWindows iterator API. Its cloning implementation could leave a buffer partially initialized before calling user-provided cloning code. If that code panicked, the buffer’s destructor could attempt to access uninitialized memory.

Microsoft said the issue was fixed by keeping the partially initialized buffer from being dropped until its contents were fully written.

AI-assisted research examines operating-system interactions

Microsoft used Hyenas, its FORGE Lab research version of codename MDASH, an AI-powered vulnerability-scanning system, to investigate the Rust standard library.

The company said some of the bugs were identified with Hyenas’ assistance. Researchers subsequently examined the underlying code, reproduced the problems, assessed their security impact and worked with Rust maintainers to report them.

Microsoft said the third category of bugs, involving interactions between Rust and the underlying operating system, is particularly difficult to identify through traditional static analysis.

These issues can involve process-wide state, memory mappings, system calls and interactions with the C library. Detecting them requires understanding how the operating system behaves alongside the application code.

Language models can help investigate these relationships by drawing on knowledge of operating-system and library interfaces, Microsoft said.

The findings also illustrate why a soundness bug in Rust’s standard library does not automatically make every application using the language vulnerable. The issues generally require specific conditions to occur, and their practical security impact depends on whether an application can reach the affected code paths.

At publication, two issues reported by Microsoft’s team remained open, while other fixes were still under review.

Rust is increasingly being adopted for security-sensitive software and infrastructure. Microsoft uses it as a Tier-1 internal programming language alongside C++, C# and TypeScript. Other projects using or adopting the language include Android, the Linux kernel, Cloudflare infrastructure and GitHub Copilot’s agent runtime.

Microsoft said the research is also informing the development of codename MDASH, which brings agentic vulnerability discovery into Microsoft Defender. Findings can additionally feed into Microsoft Perception, its multi-agent security system, where specialized agents can use vulnerability research results to prioritize testing, validate exploitability and support remediation.

Leave a Reply

Your email address will not be published. Required fields are marked *