use crate::packs::{DestructivePattern, Pack, PatternSuggestion, SafePattern};
use crate::{destructive_pattern, safe_pattern};
const CHMOD_777_SUGGESTIONS: &[PatternSuggestion] = &[
PatternSuggestion::new(
"chmod 755 {path}",
"Owner can write; others can read/execute (safer default)",
),
PatternSuggestion::new(
"chmod u+x {path}",
"Only add execute for owner instead of world-writable permissions",
),
];
const CHOWN_RECURSIVE_SUGGESTIONS: &[PatternSuggestion] = &[
PatternSuggestion::new(
"chown {user} {path}",
"Change ownership of a single path first",
),
PatternSuggestion::new(
"find {path} -maxdepth 1 -exec chown {user} {} \\;",
"Limit ownership changes to top-level entries",
),
];
#[must_use]
pub fn create_pack() -> Pack {
Pack {
id: "system.permissions".to_string(),
name: "Permissions",
description: "Protects against dangerous permission changes like chmod 777, \
recursive chmod/chown on system directories",
keywords: &["chmod", "chown", "chgrp", "setfacl"],
safe_patterns: create_safe_patterns(),
destructive_patterns: create_destructive_patterns(),
keyword_matcher: None,
safe_regex_set: None,
safe_regex_set_is_complete: false,
}
}
fn create_safe_patterns() -> Vec<SafePattern> {
vec![
safe_pattern!(
"chmod-non-recursive",
r"chmod\s+(?!-[rR])(?:\d{3,4}|[ugoa][+-][rwxXst]+)\s+[^/]"
),
safe_pattern!("stat", r"\bstat\b"),
safe_pattern!("ls-perms", r"ls\s+.*-[a-zA-Z]*l"),
safe_pattern!("getfacl", r"\bgetfacl\b"),
safe_pattern!("namei", r"\bnamei\b"),
]
}
fn create_destructive_patterns() -> Vec<DestructivePattern> {
vec![
destructive_pattern!(
"chmod-777",
r#"chmod\s+(?:.*\s+)?["'=]?0*777(?:[\s"']|$)"#,
"chmod 777 makes files world-writable. This is a security risk.",
High,
"chmod 777 grants read/write/execute to everyone. This can expose sensitive \
files and allow unauthorized modification. Prefer least-privilege permissions \
that only grant the specific access needed.",
CHMOD_777_SUGGESTIONS
),
destructive_pattern!(
"chmod-recursive-root",
r"chmod\s+(?:.*(?:-[rR]|--recursive)).*\s+/(?:$|bin|boot|dev|etc|lib|lib64|opt|proc|root|run|sbin|srv|sys|usr|var)\b",
"chmod -R on system directories can break system permissions.",
Critical,
"Recursively changing permissions on system directories can render the system \
unbootable, break package management, and disrupt every running service. Many \
system files require specific permission bits to function correctly.\n\n\
Check current permissions first:\n \
ls -la /path/to/directory\n\n\
Apply changes to a specific subdirectory instead of the whole tree."
),
destructive_pattern!(
"chown-recursive-root",
r"chown\s+(?:.*(?:-[rR]|--recursive)).*\s+/(?:$|bin|boot|dev|etc|lib|lib64|opt|proc|root|run|sbin|srv|sys|usr|var)\b",
"chown -R on system directories can break system ownership.",
High,
"Recursive ownership changes on system directories can disrupt services, \
break package-managed files, and be difficult to undo. Start with a single \
path or a shallow find before applying broader changes.",
CHOWN_RECURSIVE_SUGGESTIONS
),
destructive_pattern!(
"chmod-setuid",
r"chmod\s+.*u\+s|chmod\s+[4-7]\d{3}",
"Setting setuid bit (chmod u+s) is a security-sensitive operation.",
High,
"The setuid bit causes a program to run with the file owner's privileges \
regardless of who executes it. If set on the wrong binary, any user can \
gain elevated access. This is a common privilege escalation vector.\n\n\
Verify the file and owner first:\n \
ls -la <file>\n\n\
Find existing setuid files:\n \
find / -perm -4000 -type f 2>/dev/null"
),
destructive_pattern!(
"chmod-setgid",
r"chmod\s+.*g\+s|chmod\s+[2367]\d{3}",
"Setting setgid bit (chmod g+s) is a security-sensitive operation.",
High,
"The setgid bit on an executable causes it to run with the file group's \
privileges. On a directory, new files inherit the directory's group. \
Misapplication can grant unintended group access to sensitive resources.\n\n\
Check current group ownership:\n \
ls -la <file>\n\n\
Find existing setgid files:\n \
find / -perm -2000 -type f 2>/dev/null"
),
destructive_pattern!(
"chown-to-root",
r"chown\s+.*root[:\s]",
"Changing ownership to root should be done carefully.",
High,
"Transferring file ownership to root makes the files inaccessible to normal \
users and may break applications that need to write to those files. Services \
running as non-root users will lose access.\n\n\
Check who currently owns the file:\n \
ls -la <path>\n\n\
Consider using group ownership instead:\n \
chgrp <group> <path>"
),
destructive_pattern!(
"setfacl-all",
r"setfacl\s+.*-[rR].*\s+/(?:$|bin|boot|dev|etc|lib|lib64|opt|proc|root|run|sbin|srv|sys|usr|var)\b",
"setfacl -R on system directories can modify access control across the filesystem.",
Critical,
"Recursively modifying ACLs on system directories changes fine-grained access \
control for every file in the tree. This can override traditional Unix \
permissions and grant or revoke access in unexpected ways, breaking services \
and security boundaries.\n\n\
Review current ACLs first:\n \
getfacl <path>\n\n\
Apply to a specific file instead of recursively:\n \
setfacl -m u:<user>:rwx <specific-file>"
),
]
}