CVE-2022-21658
Medium · 6.3CVSS
6.3
EPSS
1.4%
Published
Jan 20, 2022
CISA due date
—
Cloudanix analysis
A flaw in a popular programming language's file-deletion tool could let attackers delete important system files by swapping shortcuts at just the right moment.
- Exploitation
- Local Privilege
- Attacker needs
- Local User
- Complexity
- High
- Impact
- Data Tampering
- Component
- Library
- Class
- Race Condition
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Race condition in std::fs::remove_dir_all enables symlink following (CWE-363), allowing a privileged process to delete attacker-controlled targets during recursive directory removal.
Why it matters to the business
Privileged Rust-based daemons or setuid binaries on affected systems could suffer unauthorized deletion of files and directories, causing data loss or service disruption; low urgency given stable low EPSS, no KEV listing, and publication over four years ago, though privileged contexts remain highest risk.
How an attack unfolds
An attacker with local access prepares a directory tree containing symlinks, then triggers a privileged Rust program calling remove_dir_all while racing to swap links to point at protected files; the available public exploit demonstrates the timing window on unpatched 1.0.0-1.58.0 toolchains.
How to fix it
Upgrade Rust toolchain to 1.58.1 or later; apply u-boot fixes including 2022.07+dfsg-1 (Debian 12/13), 2020.10+dfsg-1ubuntu0~18.04.3 (Ubuntu 18.04), 2021.01+dfsg-3ubuntu0~20.04.5 (Ubuntu 20.04), and 2022.01+dfsg-2ubuntu2.3 (Ubuntu 22.04). macOS <10.10 and REDOX targets receive no mitigation.
How to confirm the fix worked
Run rustc --version to confirm >=1.58.1; verify u-boot package versions match listed fixed releases; test remove_dir_all behavior under symlink race conditions on updated builds.
Typical attack path
- Locate a privileged process invoking remove_dir_all on a writable path
- Create initial directory structure with placeholder files
- Race symlink creation/replacement during recursive deletion
- Observe deletion of attacker-chosen targets outside the original directory
How to detect it
Review system and application logs for unexpected deletions of files outside expected directories during execution of Rust-compiled binaries; correlate with process creation timestamps around remove_dir_all calls; no widespread threat-actor campaigns reported.
What your security team should do
- Prioritize Rust 1.58.1+ deployment for any privileged or daemon code
- Audit call sites of remove_dir_all in internal Rust applications
- Track downstream dependents for u-boot updates in Debian/Ubuntu fleets
- Disable or sandbox affected binaries on unsupported macOS/REDOX platforms
The record
Rust is a multi-paradigm, general-purpose programming language designed for performance and safety, especially safe concurrency. The Rust Security Response WG was notified that the `std::fs::remove_dir_all` standard library function is vulnerable a race condition enabling symlink following (CWE-363). An attacker could use this security issue to trick a privileged program into deleting files and directories the attacker couldn't otherwise access or delete. Rust 1.0.0 through Rust 1.58.0 is affected by this vulnerability with 1.58.1 containing a patch. Note that the following build targets don't have usable APIs to properly mitigate the attack, and are thus still vulnerable even with a patched toolchain: macOS before version 10.10 (Yosemite) and REDOX. We recommend everyone to update to Rust 1.58.1 as soon as possible, especially people developing programs expected to run in privileged contexts (including system daemons and setuid binaries), as those have the highest risk of being affected by this. Note that adding checks in your codebase before calling remove_dir_all will not mitigate the vulnerability, as they would also be vulnerable to race conditions like remove_dir_all itself. The existing mitigation is working as intended outside of race conditions.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| AlmaLinux:8 | cargo | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | cargo-doc | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | clippy | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rls | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-analysis | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-debugger-common | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-doc | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-gdb | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-lldb | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-src | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-std-static | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-std-static-wasm32-unknown-unknown | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-std-static-wasm32-wasi | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rust-toolset | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| AlmaLinux:8 | rustfmt | 0 | 1.58.1-1.module_el8.6.0+2748+176088b3 |
| Debian:11 | rustc | 0 | No fix |
| Debian:12 | rustc | 0 | 1.57.0+dfsg1-1 |
| Debian:13 | rustc | 0 | 1.57.0+dfsg1-1 |
| Mageia:8 | rust | 0 | 1.57.0-1.1.mga8 |
| Red Hat:enterprise_linux:8::appstream | cargo | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | cargo-debuginfo | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | cargo-doc | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | clippy | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | clippy-debuginfo | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rls | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rls-debuginfo | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-analysis | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-debugger-common | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-debuginfo | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-debugsource | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-doc | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-gdb | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-lldb | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-src | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-std-static | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-std-static-wasm32-unknown-unknown | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-std-static-wasm32-wasi | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rust-toolset | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rustfmt | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Red Hat:enterprise_linux:8::appstream | rustfmt-debuginfo | 0 | 0:1.58.1-1.module+el8.6.0+14021+586eff1a |
| Rocky Linux:8 | rust | 0 | 0:1.58.1-1.module+el8.6.0+826+60f85975 |
| Rocky Linux:8 | rust-toolset | 0 | 0:1.58.1-1.module+el8.6.0+826+60f85975 |
| SUSE:Enterprise Storage 6 | rust | 0 | 1.53.0-22.1 |
| SUSE:Enterprise Storage 7 | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise High Performance Computing 15 SP1-ESPOS | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise High Performance Computing 15 SP1-LTSS | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise High Performance Computing 15 SP2-ESPOS | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise High Performance Computing 15 SP2-LTSS | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise High Performance Computing 15-ESPOS | rust | 0 | 1.53.0-3.40.1 |
| SUSE:Linux Enterprise High Performance Computing 15-LTSS | rust | 0 | 1.53.0-3.40.1 |
| SUSE:Linux Enterprise Module for Development Tools 15 SP3 | rust | 0 | 1.59.0-150300.21.20.1 |
| SUSE:Linux Enterprise Module for Development Tools 15 SP3 | rust1.55 | 0 | 1.55.0-150300.7.6.1 |
| SUSE:Linux Enterprise Module for Development Tools 15 SP3 | rust1.56 | 0 | 1.56.1-150300.7.6.1 |
| SUSE:Linux Enterprise Module for Development Tools 15 SP3 | rust1.57 | 0 | 1.57.0-150300.7.7.1 |
| SUSE:Linux Enterprise Module for Development Tools 15 SP3 | rust1.58 | 0 | 1.58.0-150300.7.3.1 |
| SUSE:Linux Enterprise Module for Development Tools 15 SP3 | rust1.59 | 0 | 1.59.0-150300.7.4.2 |
| SUSE:Linux Enterprise Real Time 15 SP2 | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise Server 15 SP1-BCL | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise Server 15 SP1-LTSS | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise Server 15 SP2-BCL | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise Server 15 SP2-LTSS | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise Server 15-LTSS | rust | 0 | 1.53.0-3.40.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 | rust | 0 | 1.53.0-3.40.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP1 | rust | 0 | 1.53.0-22.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP2 | rust | 0 | 1.53.0-22.1 |
| SUSE:Manager Proxy 4.1 | rust | 0 | 1.53.0-22.1 |
| SUSE:Manager Retail Branch Server 4.1 | rust | 0 | 1.53.0-22.1 |
| SUSE:Manager Server 4.1 | rust | 0 | 1.53.0-22.1 |
| SUSE:Package Hub 15 SP3 | libredwg | 0 | 0.12.5-bp153.2.3.1 |
| Ubuntu:14.04:LTS | rustc | 0 | No fix |
| Ubuntu:16.04:LTS | rustc | 0 | No fix |
| Ubuntu:20.04:LTS | rustc | 0 | 1.59.0+dfsg1~ubuntu1~llvm-1~ubuntu1~20.04.2 |
| Ubuntu:Pro:14.04:LTS | rustc | 0 | No fix |
| Ubuntu:Pro:16.04:LTS | rustc | 0 | No fix |
| openSUSE:Leap 15.3 | libredwg | 0 | 0.12.5-bp153.2.3.1 |
| openSUSE:Leap 15.3 | rust | 0 | 1.53.0-22.1 |
| openSUSE:Leap 15.3 | rust | 0 | 1.59.0-150300.21.20.1 |
| openSUSE:Leap 15.3 | rust1.55 | 0 | 1.55.0-150300.7.6.1 |
| openSUSE:Leap 15.3 | rust1.56 | 0 | 1.56.1-150300.7.6.1 |
| openSUSE:Leap 15.3 | rust1.57 | 0 | 1.57.0-150300.7.7.1 |
| openSUSE:Leap 15.3 | rust1.58 | 0 | 1.58.0-150300.7.3.1 |
| openSUSE:Leap 15.3 | rust1.59 | 0 | 1.59.0-150300.7.4.2 |
| openSUSE:Tumbleweed | rust1.56 | 0 | 1.56.1-4.1 |
| openSUSE:Tumbleweed | rust1.57 | 0 | 1.57.0-3.1 |
| openSUSE:Tumbleweed | rust1.58 | 0 | 1.58.0-2.1 |
Related vulnerabilities
- CVE-2025-52565 container escape due to /dev/console mount and related races CWE-363
- CVE-2025-62596 youki container escape and denial of service due to arbitrary write gadgets and procfs… CWE-363
- CVE-2025-62161 youki container escape via "masked path" abuse due to mount race conditions CWE-363
- GHSA-vf95-55w6-qmrf youki container escape and denial of service due to arbitrary write gadgets and procfs… CWE-363
- GHSA-4g74-7cff-xcv8 youki container escape via "masked path" abuse due to mount race conditions CWE-363
- CVE-2025-31133 runc container escape via "masked path" abuse due to mount race conditions CWE-363
- CVE-2025-52881 runc container escape and denial of service due to arbitrary write gadgets and procfs… CWE-363
- CVE-2026-53613 util-linux is a random collection of Linux utilities. CWE-367