use super::extract_command_basename;
pub fn command_might_be_dangerous(command: &str) -> bool {
let parts: Vec<&str> = command.split_whitespace().collect();
let Some(first) = parts.first() else {
return false;
};
let cmd_name = extract_command_basename(first);
match cmd_name {
"rm" => is_dangerous_rm(&parts),
"git" => is_dangerous_git_subcommand(&parts),
"sudo" => true,
"chmod" | "chown" | "chgrp" => true,
"mkfs" | "fdisk" | "parted" | "dd" => true,
"apt" | "apt-get" | "yum" | "dnf" | "pacman" | "brew" => true,
"systemctl" | "service" => true,
"kill" | "killall" | "pkill" => true,
"su" | "doas" => true,
_ => cmd_name.starts_with("mkfs."),
}
}
fn is_dangerous_rm(parts: &[&str]) -> bool {
for part in parts.iter().skip(1) {
if part.starts_with('-') {
let flags = part.trim_start_matches('-');
if flags.contains('f') {
return true;
}
}
}
false
}
fn is_dangerous_git_subcommand(parts: &[&str]) -> bool {
matches!(
parts.get(1).copied(),
Some("reset" | "rm" | "clean" | "rebase" | "push" | "force-push")
) || parts.iter().any(|arg| *arg == "--force" || *arg == "-f")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dangerous_rm_commands() {
assert!(command_might_be_dangerous("rm -rf /"));
assert!(command_might_be_dangerous("rm -f file.txt"));
assert!(command_might_be_dangerous("rm -rf /tmp/test"));
assert!(command_might_be_dangerous("rm -fr /tmp/test"));
}
#[test]
fn test_non_dangerous_rm_commands() {
assert!(!command_might_be_dangerous("rm file.txt"));
assert!(!command_might_be_dangerous("rm -r dir"));
assert!(!command_might_be_dangerous("rm -i file.txt"));
}
#[test]
fn test_dangerous_git_commands() {
assert!(command_might_be_dangerous("git reset --hard"));
assert!(command_might_be_dangerous("git reset HEAD~1"));
assert!(command_might_be_dangerous("git rm file.txt"));
assert!(command_might_be_dangerous("git clean -fd"));
assert!(command_might_be_dangerous("git push --force"));
assert!(command_might_be_dangerous("git rebase -i HEAD~3"));
}
#[test]
fn test_non_dangerous_git_commands() {
assert!(!command_might_be_dangerous("git status"));
assert!(!command_might_be_dangerous("git log"));
assert!(!command_might_be_dangerous("git diff"));
assert!(!command_might_be_dangerous("git add file.txt"));
assert!(!command_might_be_dangerous("git commit -m 'test'"));
}
#[test]
fn test_sudo_always_dangerous() {
assert!(command_might_be_dangerous("sudo ls"));
assert!(command_might_be_dangerous("sudo rm file.txt"));
assert!(command_might_be_dangerous("sudo apt install foo"));
}
#[test]
fn test_permission_commands_dangerous() {
assert!(command_might_be_dangerous("chmod 777 file"));
assert!(command_might_be_dangerous("chown root file"));
assert!(command_might_be_dangerous("chgrp admin file"));
}
#[test]
fn test_system_commands_dangerous() {
assert!(command_might_be_dangerous("mkfs.ext4 /dev/sda1"));
assert!(command_might_be_dangerous("fdisk /dev/sda"));
assert!(command_might_be_dangerous("dd if=/dev/zero of=/dev/sda"));
}
#[test]
fn test_package_managers_dangerous() {
assert!(command_might_be_dangerous("apt install foo"));
assert!(command_might_be_dangerous("apt-get remove bar"));
assert!(command_might_be_dangerous("brew install baz"));
assert!(command_might_be_dangerous("pacman -S foo"));
}
#[test]
fn test_service_management_dangerous() {
assert!(command_might_be_dangerous("systemctl restart nginx"));
assert!(command_might_be_dangerous("service apache2 stop"));
}
#[test]
fn test_process_killing_dangerous() {
assert!(command_might_be_dangerous("kill -9 1234"));
assert!(command_might_be_dangerous("killall firefox"));
assert!(command_might_be_dangerous("pkill -f python"));
}
#[test]
fn test_privilege_escalation_dangerous() {
assert!(command_might_be_dangerous("su -"));
assert!(command_might_be_dangerous("doas ls"));
}
#[test]
fn test_safe_commands_not_dangerous() {
assert!(!command_might_be_dangerous("ls -la"));
assert!(!command_might_be_dangerous("cat file.txt"));
assert!(!command_might_be_dangerous("grep pattern file"));
assert!(!command_might_be_dangerous("find . -name '*.rs'"));
assert!(!command_might_be_dangerous("echo hello"));
}
#[test]
fn test_full_path_dangerous_commands() {
assert!(command_might_be_dangerous("/usr/bin/sudo ls"));
assert!(command_might_be_dangerous("/bin/rm -rf /tmp/test"));
assert!(command_might_be_dangerous("/usr/bin/git reset --hard"));
}
#[test]
fn test_empty_command() {
assert!(!command_might_be_dangerous(""));
assert!(!command_might_be_dangerous(" "));
}
}