pub mod audit;
pub mod cache;
pub mod command_db;
pub mod dangerous_commands;
pub mod safe_command_registry;
pub mod shell_parser;
pub mod unified;
#[cfg(windows)]
pub mod windows;
#[cfg(windows)]
pub mod windows_cmdlet_db;
#[cfg(windows)]
pub mod windows_com_analyzer;
#[cfg(windows)]
pub mod windows_enhanced;
#[cfg(windows)]
pub mod windows_registry_filter;
#[cfg(test)]
mod integration_tests;
pub use audit::{AuditEntry, SafetyAuditLogger};
pub use cache::SafetyDecisionCache;
pub use command_db::CommandDatabase;
pub use dangerous_commands::command_might_be_dangerous;
pub use safe_command_registry::{SafeCommandRegistry, SafetyDecision};
pub use shell_parser::parse_bash_lc_commands;
pub use unified::{
EvaluationReason, EvaluationResult, PolicyAwareEvaluator, UnifiedCommandEvaluator,
};
#[cfg(windows)]
pub use windows_cmdlet_db::{CmdletCategory, CmdletDatabase, CmdletInfo, CmdletSeverity};
#[cfg(windows)]
pub use windows_com_analyzer::{ComObjectAnalyzer, ComObjectContext, ComObjectInfo, ComRiskLevel};
#[cfg(windows)]
pub use windows_enhanced::is_dangerous_windows_enhanced;
#[cfg(windows)]
pub use windows_registry_filter::{
RegistryAccessFilter, RegistryAccessPattern, RegistryPathInfo, RegistryRiskLevel,
};
pub fn is_safe_command(registry: &SafeCommandRegistry, command: &[String]) -> bool {
if command.is_empty() {
return false;
}
if command_might_be_dangerous(command) {
return false;
}
matches!(registry.is_safe(command), SafetyDecision::Allow)
}
pub fn shell_string_might_be_dangerous(command: &str) -> bool {
if let Ok(parsed_commands) = shell_parser::parse_shell_commands(command)
&& parsed_commands
.iter()
.any(|cmd| !cmd.is_empty() && command_might_be_dangerous(cmd))
{
return true;
}
let fallback_tokens: Vec<String> = command
.split_whitespace()
.map(ToString::to_string)
.collect();
!fallback_tokens.is_empty() && command_might_be_dangerous(&fallback_tokens)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_command_is_not_safe() {
let registry = SafeCommandRegistry::new();
assert!(!is_safe_command(®istry, &[]));
}
#[test]
fn shell_string_detects_dangerous_sequence() {
assert!(shell_string_might_be_dangerous(
"echo ok && git reset --hard HEAD~1"
));
}
}