Jul 6, 2026·6 min read·18 visits
A vulnerability in uutils/coreutils chmod allows local bypass of '--preserve-root' safety checks using unnormalized paths like '/../', leading to recursive root permission destruction.
A path validation bypass vulnerability exists in the chmod utility of uutils/coreutils before version 0.6.0. The '--preserve-root' safety mechanism relies on a literal string comparison, allowing local users to bypass root directory protection via unnormalized paths (such as '/../' or symbolic links) and recursively alter system-wide permissions.
The uutils/coreutils package is a cross-platform rewrite of the GNU coreutils suite in Rust. The chmod utility is a core component used to modify file and directory permissions across different filesystems. When operating in recursive mode via the -R or --recursive flags, the utility poses a significant risk to system stability if executed on the root directory. To protect against accidental system-wide permission modifications, both GNU coreutils and uutils/coreutils implement a safety mechanism named --preserve-root which is enabled by default.
This safety mechanism is designed to abort execution immediately if the target of a recursive command is identified as the filesystem root (/). However, a path validation bypass vulnerability exists in the chmod utility of uutils/coreutils prior to version 0.6.0. Because the software fails to canonicalize paths before performing the root protection check, attackers or local users can circumvent the validation logic. This bypass allows the utility to execute destructive operations on the root directory, causing system-wide permission loss.
The vulnerability is classified as CWE-22 (Improper Limitation of a Pathname to a Restricted Directory). It exposes systems to complete denial of service and structural breakdown if a recursive chmod command is executed on paths that resolve logically to root but bypass literal checks.
The root cause of this vulnerability lies in the implementation of the path comparison check inside the recursive validator in src/uu/chmod/src/chmod.rs. To identify if the user-supplied target path points to the filesystem root, the utility performs a direct, literal comparison: file == Path::new("/"). This comparison is lexical and syntax-dependent rather than logical or semantic.
On UNIX and Linux operating systems, multiple syntactically unique paths resolve to the exact same physical directory. Specifically, the path /../ refers directly to the root directory because the parent directory of the root is recursively evaluated as the root itself. Similarly, redundant path delimiters (such as //) or relative-path tokens (such as /./) are resolved by the OS kernel to the root directory during system calls.
Because the comparison check in chmod.rs only verifies if the unnormalized string or path is strictly equal to /, it fails to recognize /../ or // as equivalent paths. As a result, when an execution is triggered with /../ as the argument, the conditional block evaluating the safety guard returns false, thereby authorizing the recursive directory traversal and permission changes.
An examination of the vulnerable code segment in src/uu/chmod/src/chmod.rs shows the reliance on a literal check. The snippet below highlights the vulnerable logic before patch application:
// Vulnerable check in chmod.rs
if self.recursive && self.preserve_root && file == Path::new("/") {
return Err(ChmodError::PreserveRoot("/".into()).into());
}The fix introduced in Git commit 413055b378fa6fe2299c5e5f538c8e6e841ab810 replaces this literal comparison with a dedicated helper function Self::is_root(file) that leverages absolute path resolution:
// Patched check in chmod.rs
if self.recursive && self.preserve_root && Self::is_root(file) {
return Err(ChmodError::PreserveRoot("/".into()).into());
}
// Helper function implementing canonicalization
fn is_root(file: impl AsRef<Path>) -> bool {
matches!(fs::canonicalize(&file), Ok(p) if p == Path::new("/"))
}The function is_root invokes std::fs::canonicalize(), which resolves all intermediate symbolic links, redundant separators, and relative directory traversals like .. and .. The resulting absolute path p is then verified against the literal root path. If the resolved path matches /, the safety guard successfully triggers, throwing an error and terminating the command before execution begins.
Exploitation of this vulnerability requires local shell access to execute the chmod utility, or the ability to influence arguments passed to a recursive execution of chmod. The most immediate attack scenario involves an unprivileged local user or an administrative account mistakenly executing a recursive permission change. Under normal conditions, attempting to execute a recursive permission deletion on the root directory is blocked by the default safety configuration.
To bypass this check, an operator or local actor can execute the following command:
chmod -R --preserve-root 000 /../Because the utility fails to canonicalize /../, it bypasses the safety guard. The OS then processes the target as the filesystem root, recursively descending through every directory starting from the root. This results in the complete loss of all file permissions, rendering the operating system inoperable. Symbolic links pointing to / can also be exploited to trigger similar outcomes if the link itself is targeted during execution.
The security implications of bypassing --preserve-root are substantial, as it leads directly to local denial of service and structural system failure. If executed with high privileges, such as root or sudo, the system loses all capability to load shared libraries, run system binaries, or authenticate users due to the destruction of standard UNIX file permissions (e.g., setuid flags on /bin/sudo or read permissions on configuration files).
While the fix in version 0.6.0 resolves simple path-traversal bypasses using canonicalization, certain advanced vectors remain relevant for security engineers to consider. For example, a Time-of-Check to Time-of-Use (TOCTOU) race condition is theoretically possible. If an operator starts a recursive chmod on a benign directory, an attacker with write access to the parent directories could swap the target directory with a symbolic link to the root directory during the active traversal, bypassing the initial canonicalization check.
Additionally, std::fs::canonicalize() requires that the path elements exist and are accessible. If path resolution fails due to intermediate permission restrictions, the helper function is_root evaluates to false. A more complete fix, similar to the implementation in GNU coreutils, would compare the device identifier (st_dev) and inode number (st_ino) of the target path against the root mount point to ensure absolute identity resolution regardless of the directory string state.
The primary remediation path is upgrading uutils/coreutils to version 0.6.0 or later. This release integrates the canonicalization fix that secures the --preserve-root guard against directory traversal bypass vectors. If immediate upgrading is not possible, organizations should deploy wrapper scripts or monitoring rules to detect and block recursive execution of chmod containing parent directory tokens.
Detection of exploit attempts or accidental execution can be achieved by monitoring shell history and system audit logs for suspicious execution parameters. Specifically, look for command invocations matching the pattern chmod -R or chmod --recursive followed by arguments containing /.. or other non-standard root path representations.
In highly sensitive environments, administrators can configure system policies (such as AppArmor or SELinux) to restrict the execution of recursive permission changes on system-level directories. This restricts the potential blast radius of both accidental errors and malicious exploitation.
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
uutils/coreutils uutils | < 0.6.0 | 0.6.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Local (AV:L) |
| CVSS v3.1 Score | 7.3 |
| EPSS Score | 0.00175 |
| EPSS Percentile | 7.13% |
| Impact | Local Denial of Service / Structural Permissions Failure |
| Exploit Status | Proof of Concept Available |
| CISA KEV Status | Not Listed |
The product uses unsanitized input to construct a pathname that should be within a restricted directory, but it does not properly resolve or neutralize paths that traverse outside of the restricted directory.
A security vulnerability in Copier versions 9.5.0 through 9.15.1 allows unauthenticated remote code execution via crafted HTTP requests or local paths containing traversal sequences. The trust-evaluation mechanism compares target repository paths or URLs against trusted prefixes using unnormalized string comparison, while the subsequent fetching mechanism normalizes the path before cloning. Attackers can exploit this asymmetry to bypass security warning prompts and execute arbitrary commands under the local user context.
GeoLens before version 1.2.4 contains multiple critical-tier security vulnerabilities including improper authorization in metadata access, tile cache scope leakage, dataset title enumeration, weak default credentials, and denial of service via STAC POST search.
CVE-2026-55694 is a chained Information Disclosure and Insecure Direct Object Reference (IDOR) vulnerability in Snipe-IT prior to version 8.6.3. The vulnerability allows authenticated, restricted users to completely bypass randomized file-naming security controls, leak the obfuscated filenames of signed End User License Agreements (EULAs), and subsequently download these confidential documents across tenant boundaries.
Snipe-IT is an IT asset/license management system. Prior to 8.6.3, any activated account can request /maintenances/{id} and read maintenance records for assets in the same company without asset or maintenance permission. app/Http/Controllers/MaintenancesController.php show() renders the record without authorize(), while company-scoped route-model binding only prevents access to other companies. Disclosed fields include asset tags, suppliers, purchase costs, notes, and dates. This issue is fixed in version 8.6.3.
A Stored DOM-based Cross-Site Scripting (DOM XSS) vulnerability exists in Snipe-IT versions prior to 8.6.2. The vulnerability occurs when a stored manufacturer or supplier name is converted to CamelCase and rendered within the 'data-selected-count-id' attribute of a table. Client-side JavaScript retrieves this decoded attribute and performs unsafe string concatenation, passing it directly into jQuery's '.after()' method, enabling authenticated attackers to execute arbitrary JavaScript in the victim's session.
CVE-2026-62673 (also known as CVE-2026-62230 and GHSA-vwg3-w8w3-pc79) is a high-severity security bypass vulnerability in the Grav CMS. It permits unauthenticated remote attackers to circumvent directory and file access policies defined in Apache .htaccess. This flaw allows direct retrieval of sensitive configuration files, system-level credentials, and database equivalents from case-insensitive host filesystems.