#![allow(dead_code)]
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExecutionTier {
Allow,
Sandbox,
Deny,
}
impl fmt::Display for ExecutionTier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ExecutionTier::Allow => write!(f, "ALLOW"),
ExecutionTier::Sandbox => write!(f, "SANDBOX"),
ExecutionTier::Deny => write!(f, "DENY"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GuardDecision {
pub tier: ExecutionTier,
pub reason: String,
pub previously_failed: bool,
}
impl GuardDecision {
pub fn new(tier: ExecutionTier, reason: impl Into<String>) -> Self {
Self {
tier,
reason: reason.into(),
previously_failed: false,
}
}
pub fn with_previous_failure(mut self) -> Self {
self.previously_failed = true;
if self.tier == ExecutionTier::Allow {
self.tier = ExecutionTier::Sandbox;
self.reason = format!(
"{} (elevated to sandbox due to previous failure)",
self.reason
);
}
self
}
pub fn is_permitted(&self) -> bool {
matches!(self.tier, ExecutionTier::Allow | ExecutionTier::Sandbox)
}
pub fn is_denied(&self) -> bool {
self.tier == ExecutionTier::Deny
}
}
const ALLOW_PATTERNS: &[&str] = &[
"ls",
"ll",
"dir",
"cat",
"head",
"tail",
"less",
"more",
"echo",
"printf",
"pwd",
"whoami",
"uname",
"date",
"uptime",
"grep",
"rg",
"find",
"fd",
"git status",
"git log",
"git diff",
"git show",
"git branch",
"git push",
"git pull",
"git fetch",
"git clone",
"git checkout",
"git add",
"git commit",
"git merge",
"git rebase",
"git cherry-pick",
"cargo check",
"cargo clippy",
"cargo fmt",
"cargo doc",
"terraform plan",
"terraform validate",
"terraform show",
"docker ps",
"docker images",
"docker logs",
"kubectl get",
"kubectl describe",
"kubectl logs",
"tar -tvf",
"tar --list",
"zipinfo",
"unzip -l",
"md5sum",
"sha256sum",
"sha1sum",
"wc",
"sort",
"uniq",
"cut",
"awk",
"sed",
"tr",
"which",
"whereis",
"type",
"env",
"printenv",
"history",
"man",
"help",
"info",
"clear",
"reset",
"true",
"false",
"exit",
];
const DENY_PATTERNS: &[&str] = &[
"rm -rf /",
"rm -rf /*",
"rm -rf ~",
"rm -rf $HOME",
"mkfs",
"mkfs.ext",
"mkfs.xfs",
"mkfs.btrfs",
"dd if=/dev/zero",
"dd if=/dev/random",
"dd if=/dev/urandom",
":(){ :|:& };:",
"fork bomb",
"> /dev/sda",
"> /dev/hda",
"> /dev/nvme",
"chmod -R 777 /",
"chmod -R 000 /",
"mv / /dev/null",
"rmdir /",
"rmdir /*",
"truncate -s 0 /",
"shred -n 0 -z /",
"kill -9 -1",
"kill -9 1",
"reboot",
"shutdown",
"poweroff",
"halt",
"init 0",
"init 6",
"systemctl stop",
"echo .* > /etc/passwd",
"echo .* > /etc/shadow",
];
pub fn evaluate_command(command: &str) -> GuardDecision {
let trimmed = command.trim();
for pattern in DENY_PATTERNS {
if trimmed.contains(pattern) {
return GuardDecision::new(
ExecutionTier::Deny,
format!("Matches dangerous pattern: '{}'", pattern),
);
}
}
for pattern in ALLOW_PATTERNS {
if trimmed.starts_with(pattern) {
return GuardDecision::new(
ExecutionTier::Allow,
format!("Known-safe command: '{}'", pattern),
);
}
}
GuardDecision::new(
ExecutionTier::Sandbox,
"Unknown command; execute in sandbox",
)
}
pub fn evaluate_command_with_learning(command: &str, has_failed_before: bool) -> GuardDecision {
let decision = evaluate_command(command);
if has_failed_before {
decision.with_previous_failure()
} else {
decision
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_allow_basic_commands() {
assert_eq!(evaluate_command("ls -la").tier, ExecutionTier::Allow);
assert_eq!(evaluate_command("cat file.txt").tier, ExecutionTier::Allow);
assert_eq!(evaluate_command("echo hello").tier, ExecutionTier::Allow);
assert_eq!(evaluate_command("git status").tier, ExecutionTier::Allow);
assert_eq!(evaluate_command("cargo check").tier, ExecutionTier::Allow);
}
#[test]
fn test_deny_dangerous_commands() {
assert_eq!(evaluate_command("rm -rf /").tier, ExecutionTier::Deny);
assert_eq!(
evaluate_command("dd if=/dev/zero of=/dev/sda").tier,
ExecutionTier::Deny
);
assert_eq!(
evaluate_command("mkfs.ext4 /dev/sda1").tier,
ExecutionTier::Deny
);
assert_eq!(evaluate_command("chmod -R 777 /").tier, ExecutionTier::Deny);
}
#[test]
fn test_sandbox_unknown_commands() {
assert_eq!(
evaluate_command("some-unknown-tool --flag").tier,
ExecutionTier::Sandbox
);
assert_eq!(
evaluate_command("./random-script.sh").tier,
ExecutionTier::Sandbox
);
}
#[test]
fn test_learning_elevation() {
let decision = evaluate_command_with_learning("git push", true);
assert_eq!(decision.tier, ExecutionTier::Sandbox);
assert!(decision.previously_failed);
assert!(decision.reason.contains("elevated to sandbox"));
}
#[test]
fn test_no_elevation_without_failure() {
let decision = evaluate_command_with_learning("git push", false);
assert_eq!(decision.tier, ExecutionTier::Allow);
assert!(!decision.previously_failed);
}
#[test]
fn test_deny_not_elevated() {
let decision = evaluate_command_with_learning("rm -rf /", true);
assert_eq!(decision.tier, ExecutionTier::Deny);
}
#[test]
fn test_sandbox_stays_sandbox() {
let decision = evaluate_command_with_learning("unknown-cmd", true);
assert_eq!(decision.tier, ExecutionTier::Sandbox);
}
#[test]
fn test_decision_permitted() {
assert!(evaluate_command("ls").is_permitted());
assert!(evaluate_command("unknown").is_permitted());
assert!(!evaluate_command("rm -rf /").is_permitted());
}
#[test]
fn test_display_tier() {
assert_eq!(format!("{}", ExecutionTier::Allow), "ALLOW");
assert_eq!(format!("{}", ExecutionTier::Sandbox), "SANDBOX");
assert_eq!(format!("{}", ExecutionTier::Deny), "DENY");
}
}