shell_sanitize_rules/
shell_meta.rs1use shell_sanitize::{Rule, RuleResult, RuleViolation};
2
3use crate::charset::CharSet;
4
5pub struct ShellMetaRule {
21 denied: CharSet,
22}
23
24const DEFAULT_DENIED: &[char] = &[
25 ';', '|', '&', '$', '`', '(', ')', '{', '}', '<', '>', '!', '#', '\\', '\'', '"', '~', '\n',
26 '\r',
27];
28
29impl Default for ShellMetaRule {
30 fn default() -> Self {
31 Self {
32 denied: CharSet::from_chars(DEFAULT_DENIED),
33 }
34 }
35}
36
37impl ShellMetaRule {
38 pub fn with_denied(denied: Vec<char>) -> Self {
40 Self {
41 denied: CharSet::from_chars(&denied),
42 }
43 }
44
45 pub fn with_extra_denied(extra: &[char]) -> Self {
47 let mut chars: Vec<char> = DEFAULT_DENIED.to_vec();
48 chars.extend(extra);
49 Self {
50 denied: CharSet::from_chars(&chars),
51 }
52 }
53}
54
55impl Rule for ShellMetaRule {
56 fn name(&self) -> &'static str {
57 "shell_meta"
58 }
59
60 fn check(&self, input: &str) -> RuleResult {
61 let violations: Vec<_> = input
62 .char_indices()
63 .filter(|(_, c)| self.denied.contains(*c))
64 .map(|(i, c)| {
65 RuleViolation::new(self.name(), format!("shell metacharacter {:?} found", c))
66 .at(i)
67 .with_fragment(c.to_string())
68 })
69 .collect();
70
71 if violations.is_empty() {
72 Ok(())
73 } else {
74 Err(violations)
75 }
76 }
77}