| Crates.io | privesc |
| lib.rs | privesc |
| version | 1.2.0 |
| created_at | 2025-12-23 22:42:04.171651+00 |
| updated_at | 2025-12-25 23:12:10.822285+00 |
| description | Small utility library for multi-platform privilege escalation |
| homepage | |
| repository | https://github.com/quincy-rs/privesc |
| max_upload_size | |
| id | 2002490 |
| size | 65,855 |
Cross-platform privilege escalation for Rust.
Run commands with elevated privileges on macOS, Linux, and Windows.
There is explicit validation for the program parameter to ensure that it is an absolute path to an executable file.
This is done in order to ensure that the target executable has not been tampered with or is not a symlink to a malicious binary (PATH hijacking etc.)
use privesc::PrivilegedCommand;
fn main() -> privesc::Result<()> {
let output = PrivilegedCommand::new("/usr/bin/cat")
.arg("/etc/shadow")
.run()?;
if output.success() {
if let Some(content) = output.stdout_str() {
println!("{content}");
}
}
Ok(())
}
With all options:
use privesc::PrivilegedCommand;
let output = PrivilegedCommand::new("/usr/bin/cat")
.args(["/etc/shadow", "/etc/passwd"])
.gui(true)
.prompt("Reading protected files")
.run()?;
Use spawn() to start a privileged process and continue working while it runs:
use privesc::PrivilegedCommand;
fn main() -> privesc::Result<()> {
let mut child = PrivilegedCommand::new("/usr/bin/long-task")
.spawn()?;
if let Some(id) = child.id() {
println!("Process started with ID: {id}");
}
// Do other work while the process runs...
// Check if done without blocking
if let Some(status) = child.try_wait()? {
println!("Already finished: {status}");
}
// Block until completion
let output = child.wait()?;
println!("Exit status: {}", output.status);
Ok(())
}
| Platform | GUI mode | CLI mode | Output capture |
|---|---|---|---|
| macOS | AppleScript dialog | sudo |
Yes |
| Linux | pkexec |
sudo |
Yes |
| Windows | UAC prompt | UAC prompt | No |
CLI mode (sudo): Arguments are passed directly via Rust's Command::args(), which uses execve under the hood. No shell is involved — arguments are passed as-is to the target program regardless of special characters.
GUI mode (osascript): Arguments flow through two stages:
Command::args() (no shell, safe)quoted form of to escape each argument before passing to do shell scriptAppleScript's quoted form of wraps arguments in single quotes and escapes embedded single quotes as '\''. This prevents shell interpretation of $, backticks, spaces, and other metacharacters.
CLI mode (sudo): Arguments are passed directly via Rust's Command::args(), which uses execve under the hood. No shell is involved — arguments are passed as-is to the target program regardless of special characters.
GUI mode (pkexec): Same as CLI mode (sudo)
CLI mode (UAC via ShellExecuteExW): The Windows API takes arguments as a single string, not an array. This library implements custom escaping following Windows command-line parsing conventions:
CommandLineToArgvW rules (quotes, backslashes).bat/.cmd): Additional escaping prevents %VAR% environment variable expansion and related injection vectors (addresses CVE-2024-24576 class vulnerabilities)GUI mode (runas): Same as CLI mode (ShellExecuteExW)