cai/tests/tools/test_sensitive_guard_false_...

153 lines
5.5 KiB
Python

"""Tests for false-positive suppression in the sensitive command guard.
Verifies that tool names appearing in file paths or arguments do NOT
trigger the guard, while actual tool invocations still do.
"""
from __future__ import annotations
from unittest.mock import patch
import pytest
from cai.util.user_prompts import (
_extract_all_binaries,
detect_sensitive_command,
)
@pytest.fixture(autouse=True)
def _guard_enabled():
"""Ensure the guard is always enabled during tests."""
with patch.dict("os.environ", {"CAI_SENSITIVE_GUARD": "true", "CAI_TUI_MODE": "false"}):
yield
# ── _extract_all_binaries unit tests ──────────────────────────────────
class TestExtractAllBinaries:
def test_simple_command(self):
assert _extract_all_binaries("ls -la /tmp") == {"ls"}
def test_sudo_prefix(self):
assert _extract_all_binaries("sudo nmap -sS 10.0.0.1") == {"nmap"}
def test_pipeline(self):
assert _extract_all_binaries("nmap -sS 10.0.0.1 | grep open") == {"nmap", "grep"}
def test_chain_and(self):
assert _extract_all_binaries("whoami && nmap -sS 10.0.0.1") == {"whoami", "nmap"}
def test_chain_or(self):
assert _extract_all_binaries("false || nmap 10.0.0.1") == {"false", "nmap"}
def test_semicolon(self):
assert _extract_all_binaries("cd /tmp; nmap 10.0.0.1") == {"cd", "nmap"}
def test_env_assignment_prefix(self):
assert _extract_all_binaries("FOO=bar nmap -sS 10.0.0.1") == {"nmap"}
def test_full_path_binary(self):
assert _extract_all_binaries("/usr/bin/nmap -sS 10.0.0.1") == {"nmap"}
def test_tool_in_path_only(self):
assert _extract_all_binaries("ls -la /home/kali/nmap/") == {"ls"}
def test_multiple_prefixes(self):
assert _extract_all_binaries("sudo env nmap -sS 10.0.0.1") == {"nmap"}
# ── False positives (should NOT trigger the guard) ────────────────────
class TestFalsePositives:
def test_ls_nmap_directory(self):
is_sensitive, _, _ = detect_sensitive_command("ls -la /home/kali/nmap/")
assert not is_sensitive
def test_cat_masscan_config(self):
is_sensitive, _, _ = detect_sensitive_command("cat /opt/masscan/config.txt")
assert not is_sensitive
def test_find_shred_backup(self):
is_sensitive, _, _ = detect_sensitive_command("find / -name shred_backup")
assert not is_sensitive
def test_echo_nmap_string(self):
is_sensitive, _, _ = detect_sensitive_command("echo 'installed nmap yesterday'")
assert not is_sensitive
def test_grep_in_hydra_log(self):
is_sensitive, _, _ = detect_sensitive_command("grep error /var/log/hydra.log")
assert not is_sensitive
def test_grep_alternation_with_sudo_literal_not_sudo_privilege(self):
cmd = (
r"tail -100 /var/log/auth.log 2>/dev/null | "
r"grep -E \"(Failed|Accepted|Invalid|session opened|session closed|sudo|su:)\" | tail -50"
)
is_sensitive, _, category = detect_sensitive_command(cmd)
assert not is_sensitive
assert category == ""
def test_mkdir_nikto_output(self):
is_sensitive, _, _ = detect_sensitive_command("mkdir -p /tmp/nikto_results")
assert not is_sensitive
def test_cp_fdisk_backup(self):
is_sensitive, _, _ = detect_sensitive_command("cp /tmp/fdisk_output.txt /backup/")
assert not is_sensitive
# ── True positives (MUST trigger the guard) ───────────────────────────
class TestTruePositives:
def test_nmap_direct(self):
is_sensitive, reason, category = detect_sensitive_command("nmap -sS 10.0.0.1")
assert is_sensitive
assert category == "recon_tool"
def test_sudo_nmap(self):
is_sensitive, _, category = detect_sensitive_command("sudo nmap -sV 10.0.0.1")
assert is_sensitive
assert category == "sudo"
def test_nmap_in_pipeline(self):
is_sensitive, _, category = detect_sensitive_command("cat hosts.txt | nmap -iL -")
assert is_sensitive
assert category == "recon_tool"
def test_env_prefix_nmap(self):
is_sensitive, _, category = detect_sensitive_command("FOO=bar nmap -sS 10.0.0.1")
assert is_sensitive
assert category == "recon_tool"
def test_hydra_direct(self):
is_sensitive, _, category = detect_sensitive_command("hydra -l admin ssh://10.0.0.1")
assert is_sensitive
assert category == "recon_tool"
def test_shred_direct(self):
is_sensitive, _, category = detect_sensitive_command("shred -u /tmp/secret.txt")
assert is_sensitive
assert category == "destructive"
def test_fdisk_direct(self):
is_sensitive, _, category = detect_sensitive_command("fdisk /dev/sda")
assert is_sensitive
assert category == "destructive"
def test_sudo_rm_rf(self):
"""sudo category is NOT subject to binary post-check."""
is_sensitive, _, category = detect_sensitive_command("sudo rm -rf /")
assert is_sensitive
assert category == "sudo"
def test_full_path_nmap(self):
is_sensitive, _, category = detect_sensitive_command("/usr/bin/nmap -sS 10.0.0.1")
assert is_sensitive
assert category == "recon_tool"
def test_msfconsole(self):
is_sensitive, _, category = detect_sensitive_command("msfconsole -q")
assert is_sensitive
assert category == "recon_tool"