Skip to main content

safe_find/
lib.rs

1use std::collections::HashSet;
2use std::process::{Command, ExitStatus};
3
4/// Dangerous options for the find command
5pub const FIND_DANGEROUS_OPTIONS: &[&str] = &["-exec", "-execdir", "-ok", "-okdir", "-delete"];
6
7/// Dangerous options for the fd command  
8pub const FD_DANGEROUS_OPTIONS: &[&str] =
9    &["-x", "--exec", "-X", "--exec-batch", "-l", "--list-details"];
10
11/// Check if any dangerous options are present in the arguments
12pub fn check_dangerous_options(args: &[String], dangerous_options: &[&str]) -> Result<(), String> {
13    let dangerous_set: HashSet<&str> = dangerous_options.iter().copied().collect();
14
15    for arg in args {
16        if dangerous_set.contains(arg.as_str()) {
17            return Err(format!(
18                "Error: Dangerous option '{}' is not allowed for security reasons",
19                arg
20            ));
21        }
22    }
23
24    Ok(())
25}
26
27/// Execute a command with the given arguments
28pub fn execute_command(command_name: &str, args: &[String]) -> Result<ExitStatus, std::io::Error> {
29    let mut cmd = Command::new(command_name);
30    cmd.args(args);
31    cmd.status()
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    #[test]
39    fn test_check_dangerous_options_find() {
40        let safe_args = vec![".", "-name", "*.txt", "-type", "f"]
41            .into_iter()
42            .map(String::from)
43            .collect::<Vec<_>>();
44        assert!(check_dangerous_options(&safe_args, FIND_DANGEROUS_OPTIONS).is_ok());
45
46        let dangerous_args = vec![".", "-name", "*.txt", "-exec", "rm", "{}", ";"]
47            .into_iter()
48            .map(String::from)
49            .collect::<Vec<_>>();
50        assert!(check_dangerous_options(&dangerous_args, FIND_DANGEROUS_OPTIONS).is_err());
51    }
52
53    #[test]
54    fn test_check_dangerous_options_fd() {
55        let safe_args = vec!["*.js", "--type", "f"]
56            .into_iter()
57            .map(String::from)
58            .collect::<Vec<_>>();
59        assert!(check_dangerous_options(&safe_args, FD_DANGEROUS_OPTIONS).is_ok());
60
61        let dangerous_args = vec!["*.js", "-x", "rm"]
62            .into_iter()
63            .map(String::from)
64            .collect::<Vec<_>>();
65        assert!(check_dangerous_options(&dangerous_args, FD_DANGEROUS_OPTIONS).is_err());
66    }
67}