use std::path::Path;
pub static BLACKLISTED_PATHS: &[&str] = &[
"/etc", "/sys", "/proc", "/dev", "/boot", "/root", "/bin", "/sbin", "/usr/bin", "/usr/sbin", "/System", "/Library", "/private/etc", "/private/var/db", "C:\\Windows", "C:\\Program Files", "C:\\Program Files (x86)", "C:\\ProgramData", "C:\\System", "C:\\System32", "C:\\Windows\\System32", ];
#[must_use]
pub fn is_path_blacklisted(path: &Path) -> bool {
for blacklisted in BLACKLISTED_PATHS {
if path.starts_with(blacklisted) {
return true;
}
}
false
}
pub fn validate_path_security(path: &Path, check_symlinks: bool) -> anyhow::Result<()> {
if is_path_blacklisted(path) {
return Err(anyhow::anyhow!("Security error: Access to system directories is not allowed"));
}
if check_symlinks && path.exists() {
let metadata = std::fs::symlink_metadata(path)
.map_err(|_| anyhow::anyhow!("Failed to check path metadata"))?;
if metadata.file_type().is_symlink() {
return Err(anyhow::anyhow!(
"Security error: Symlinks are not allowed in local dependency paths"
));
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_blacklisted_paths() {
assert!(is_path_blacklisted(Path::new("/etc/passwd")));
assert!(is_path_blacklisted(Path::new("/sys/kernel")));
assert!(is_path_blacklisted(Path::new("/System/Library/CoreServices")));
assert!(is_path_blacklisted(Path::new("/private/etc/hosts")));
#[cfg(windows)]
{
assert!(is_path_blacklisted(Path::new("C:\\Windows\\System32")));
assert!(is_path_blacklisted(Path::new("C:\\Program Files\\App")));
}
assert!(!is_path_blacklisted(Path::new("/home/user/project")));
assert!(!is_path_blacklisted(Path::new("/tmp/test")));
assert!(!is_path_blacklisted(Path::new("/var/folders/temp")));
assert!(!is_path_blacklisted(Path::new("/Users/developer/work")));
}
#[test]
fn test_validate_path_security() -> anyhow::Result<()> {
validate_path_security(Path::new("/home/user/project"), false)?;
validate_path_security(Path::new("/tmp/test"), false)?;
assert!(validate_path_security(Path::new("/etc/passwd"), false).is_err());
assert!(validate_path_security(Path::new("/System/Library"), false).is_err());
Ok(())
}
}