44 CVEs in Rust Coreutils: Why the Borrow Checker Isn't Enough

Key Takeaways

- 44 CVEs were found in uutils, the Rust reimplementation of GNU coreutils shipping in Ubuntu
- Time-of-check to time-of-use (TOCTOU) race conditions formed the largest cluster of bugs
- Rust's standard library APIs make path resolution vulnerabilities easy to introduce
In April 2026, Canonical disclosed 44 CVEs in uutils, the Rust reimplementation of GNU coreutils that ships by default in Ubuntu 25.10. The vulnerabilities came from an external audit commissioned ahead of the 26.04 LTS release. Every single one of them landed in production code written by experienced Rust developers. None were caught by the borrow checker, clippy lints, or cargo audit.
Matthias Endler, who analyzed the audit results, writes that this is the most concentrated look at where Rust's safety ends that you'll find anywhere right now. The uutils team shared their audit results in detail, giving the community a rare chance to learn from real production bugs.
The Core Problem: Path Resolution Between Syscalls
The largest cluster of bugs in the audit follows one pattern. You make a syscall to check something about a file path. Then you make another syscall to act on that path. Between those two calls, an attacker with write access to a parent directory can swap the path component for a symbolic link. The kernel resolves the path from scratch on the second call, and the privileged action lands on the attacker's chosen target.
This is called a time-of-check to time-of-use (TOCTOU) race condition. It's a classic security bug that has nothing to do with memory safety. Rust's borrow checker prevents use-after-free, double-free, and data races. It does not prevent logic errors in how you sequence system calls.
These bugs are serious enough that cp, mv, and rm are still GNU implementations in Ubuntu 26.04 LTS. The Rust versions weren't safe for privileged operations.
How Rust's Standard Library Makes This Easy to Get Wrong
Rust's standard library provides ergonomic APIs like fs::metadata, File::create, fs::remove_file, and fs::set_permissions. These are the functions you reach for first. They all take a path and resolve it every time, rather than taking a file descriptor and operating relative to that.
For a normal program, this is fine. For a privileged tool that needs to be secure against local attackers, it's a trap. The safe-looking API does the unsafe thing.
Case Study: CVE-2026-35355
Here's a simplified version of the bug from the install command implementation:
// 1. Clear the destination
fs::remove_file(to)?;
// ...
// 2. Create the destination. The path is re-resolved here!
let mut dest = File::create(to)?; // follows symlinks, truncates
copy(from, &mut dest)?;Between step 1 and step 2, anyone with write access to the parent directory can plant a symlink at the destination path. Point it to /etc/shadow. File::create follows the symlink, and the privileged process overwrites /etc/shadow with whatever the source file contained.
The fix uses OpenOptions::create_new(true):
fs::remove_file(to)?;
let mut dest = OpenOptions::new()
.write(true)
.create_new(true)
.open(to)?;
copy(from, &mut dest)?;The documentation for create_new says: "No file is allowed to exist at the target location, also no (dangling) symlink." If the call succeeds, the file was created atomically. There's no window for an attacker to slip in a symlink.
What Rust Safety Actually Means
Rust guarantees memory safety in safe code. No use-after-free. No buffer overflows. No data races. These are significant wins. Memory corruption bugs are responsible for roughly 70% of critical vulnerabilities in C and C++ codebases.
But memory safety is not the same as "correct" or "secure." Rust doesn't prevent:
- Race conditions in business logic
- TOCTOU vulnerabilities in filesystem operations
- Incorrect permission checks
- Logic errors in cryptographic implementations
- SQL injection (in unsafe database code)
- Denial of service through algorithmic complexity
The uutils audit is a reminder that "rewrite it in Rust" fixes one class of bugs. It doesn't fix all bugs.
Lessons for Systems Programmers
If you're writing privileged tools in Rust, Endler's analysis suggests several practices:
- Prefer file descriptor operations over path operations when security matters
- Use OpenOptions::create_new(true) instead of File::create when creating files atomically
- Audit any code that makes multiple syscalls on the same path
- Don't assume the borrow checker catches all security bugs
Jon Seager, VP Engineering for Ubuntu, discussed Canonical's Rust adoption on the 'Rust in Production' podcast. Listeners appreciated his honesty about where Rust helps and where it doesn't.
Another critical infrastructure vulnerability disclosure affecting enterprise security
The Bigger Picture
Rust's adoption in systems programming continues to grow. The Linux kernel includes Rust. Android uses it. Microsoft and Google have both invested heavily. This is good. Memory safety bugs are a real and serious problem.
But the uutils audit shows that security requires more than memory safety. It requires correct logic. It requires understanding the threat model. It requires knowing which APIs are safe for privileged operations and which aren't.
The uutils team deserves credit for publishing the audit results. Most organizations would quietly fix the bugs and say nothing. Sharing the details lets everyone learn.
Logicity's Take
Frequently Asked Questions
What are TOCTOU vulnerabilities?
Time-of-check to time-of-use vulnerabilities occur when a program checks a condition and then acts on it, but an attacker changes the state between the check and the action. In filesystem operations, this often involves swapping a file for a symlink.
Does Rust prevent all security vulnerabilities?
No. Rust prevents memory safety bugs like buffer overflows and use-after-free. It does not prevent logic errors, race conditions, incorrect permission checks, or vulnerabilities in how syscalls are sequenced.
Why are cp, mv, and rm still GNU in Ubuntu 26.04?
The TOCTOU vulnerabilities in the Rust implementations made them unsafe for privileged operations. Until those bugs are fixed and verified, Ubuntu is shipping the GNU versions for these commands.
How do you prevent TOCTOU bugs in Rust filesystem code?
Use file descriptor operations instead of path operations where possible. Use OpenOptions::create_new(true) for atomic file creation. Avoid sequences where you check a path's properties and then act on the same path separately.
Need Help Implementing This?
Source: Hacker News: Best / Corrode Rust Consulting
Huma Shazia
Senior AI & Tech Writer
Related Articles
Browse all
Robotaxi Companies Are Hiding How Often Humans Take the Wheel
Autonomous vehicle firms like Waymo and Tesla are under scrutiny for refusing to disclose how often remote operators step in to control their self-driving cars. A Senate investigation reveals major gaps in transparency, raising safety and accountability concerns.

Wisconsin Governor Throws a Wrench in Age Verification Plans
Wisconsin Governor Tony Evers has vetoed a bill that would have required residents to verify their age before accessing adult content online, citing concerns over privacy and data security. This move comes as several other states have already implemented similar age check requirements. The veto has significant implications for the future of online age verification.

Apple's App Store Empire Under Siege: The Battle for the Future of Tech
The long-running feud between Apple and Epic Games has reached a boiling point, with Apple preparing to take its case to the Supreme Court. The tech giant is fighting to maintain control over its App Store, while Epic Games is pushing for more freedom for developers. The outcome could have far-reaching implications for the entire tech industry.

Tesla's Remote Parking Feature: The Investigation That Didn't Quite Park Itself
The US auto safety regulators have closed their investigation into Tesla's remote parking feature, but what does this mean for the future of autonomous driving? We dive into the details of the investigation and what it reveals about the technology. The National Highway Traffic Safety Administration found that crashes were rare and minor, but the investigation's closure doesn't necessarily mean the feature is completely safe.
Also Read

Invincible VS Launches April 30: Global Release Times Confirmed
Developer Quarter Up has locked in worldwide release times for Invincible VS, the 3v3 tag fighting game based on the Prime Video animated series. The game arrives on PC, Xbox, and PlayStation 5 with an 18-character roster and a story mode written in collaboration with series co-creator Robert Kirkman.
How ChatGPT Serves Ads: The Full Attribution Loop Revealed
A security researcher has reverse-engineered OpenAI's advertising infrastructure, revealing how ChatGPT injects ads into conversations using encrypted click tokens and contextual targeting. The findings expose a sophisticated two-sided platform connecting real-time ad delivery with merchant tracking.

GitHub RCE Flaw: 88% of Enterprise Servers Still Vulnerable
Wiz Research discovered a critical vulnerability in GitHub's git infrastructure that allows any authenticated user to execute arbitrary commands with a single git push. While GitHub.com was patched within 6 hours, nearly 9 in 10 GitHub Enterprise Server instances remain unpatched and at risk of full server compromise.