5c49b2134b
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 15s
CI / helm (pull_request) Successful in 23s
CI / lint (pull_request) Successful in 3m16s
CI / quality (pull_request) Successful in 3m40s
CI / security (pull_request) Successful in 4m3s
CI / typecheck (pull_request) Successful in 4m11s
CI / unit_tests (pull_request) Successful in 9m21s
CI / docker (pull_request) Successful in 1m37s
CI / e2e_tests (pull_request) Failing after 13m4s
CI / coverage (pull_request) Successful in 12m28s
CI / integration_tests (pull_request) Successful in 24m23s
CI / status-check (pull_request) Failing after 3s
CI / benchmark-regression (pull_request) Successful in 55m11s
Implement dangerous shell pattern detection with configurable pattern registry, danger level classification, and user warning system. - Domain: ShellDangerLevel enum (LOW, MEDIUM, HIGH, CRITICAL) - Domain: DangerousPattern value object with regex matching - Domain: DangerousCommandWarning value object - Domain: DangerousPatternDetector with configurable pattern registry - Application: ShellSafetyService with warn_callback and block_level - Default patterns: rm -rf, fork bomb, dd if=, mkfs, chmod 777, sudo rm, wget/curl piped to sh/bash, git push --force - BDD tests covering all pattern categories, safe commands, registry management, and service behavior ISSUES CLOSED: #1003
237 lines
11 KiB
Gherkin
237 lines
11 KiB
Gherkin
Feature: TUI Shell Danger Detection
|
|
As a TUI user
|
|
I want dangerous shell commands to be detected and warned about
|
|
So that I can avoid accidentally running destructive commands
|
|
|
|
Background:
|
|
Given the shell safety module is imported
|
|
|
|
# ── Danger level enum ────────────────────────────────────────────────────
|
|
|
|
Scenario: ShellDangerLevel enum has four levels
|
|
Then the ShellDangerLevel enum should have levels LOW MEDIUM HIGH CRITICAL
|
|
|
|
Scenario: ShellDangerLevel levels are ordered by severity
|
|
Then LOW should be less severe than MEDIUM
|
|
And MEDIUM should be less severe than HIGH
|
|
And HIGH should be less severe than CRITICAL
|
|
|
|
# ── DangerousPattern value object ────────────────────────────────────────
|
|
|
|
Scenario: DangerousPattern matches a dangerous command
|
|
Given a DangerousPattern named "test_rm" with pattern "rm -rf" at CRITICAL level
|
|
When I check if "rm -rf /" matches the pattern
|
|
Then the pattern should match
|
|
|
|
Scenario: DangerousPattern does not match a safe command
|
|
Given a DangerousPattern named "test_rm" with pattern "rm -rf" at CRITICAL level
|
|
When I check if "ls -la" matches the pattern
|
|
Then the pattern should not match
|
|
|
|
Scenario: DangerousPattern is case-insensitive by default
|
|
Given a DangerousPattern named "test_rm" with pattern "rm -rf" at CRITICAL level
|
|
When I check if "RM -RF /" matches the pattern
|
|
Then the pattern should match
|
|
|
|
# ── DangerousCommandWarning value object ─────────────────────────────────
|
|
|
|
Scenario: DangerousCommandWarning is created from a pattern
|
|
Given a DangerousPattern named "rm_root" with pattern "rm -rf /" at CRITICAL level
|
|
When I create a warning for command "rm -rf /" from the pattern
|
|
Then the warning command should be "rm -rf /"
|
|
And the warning danger level should be CRITICAL
|
|
And the warning message should contain "Critical"
|
|
And the warning message should contain "Dangerous command detected"
|
|
|
|
Scenario: DangerousCommandWarning message includes pattern description
|
|
Given a DangerousPattern named "fork_bomb" with pattern ":(){" at CRITICAL level and description "Fork bomb"
|
|
When I create a warning for command ":(){ :|:& };:" from the pattern
|
|
Then the warning message should contain "Fork bomb"
|
|
|
|
# ── DangerousPatternDetector ─────────────────────────────────────────────
|
|
|
|
Scenario: Detector uses default patterns when none provided
|
|
Given a DangerousPatternDetector with default patterns
|
|
Then the detector should have patterns registered
|
|
|
|
Scenario: Detector detects rm -rf root as CRITICAL
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "rm -rf /"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be CRITICAL
|
|
|
|
Scenario: Detector detects rm -rf wildcard as CRITICAL
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "rm -rf /*"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be CRITICAL
|
|
|
|
Scenario: Detector detects fork bomb as CRITICAL
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command ":(){ :|:& };:"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be CRITICAL
|
|
|
|
Scenario: Detector detects dd if= as HIGH
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "dd if=/dev/zero of=/dev/sda"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be HIGH
|
|
|
|
Scenario: Detector detects mkfs as HIGH
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "mkfs.ext4 /dev/sdb1"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be HIGH
|
|
|
|
Scenario: Detector detects chmod 777 as MEDIUM
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "chmod 777 /etc/passwd"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be MEDIUM
|
|
|
|
Scenario: Detector detects sudo rm as MEDIUM
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "sudo rm file.txt"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be MEDIUM
|
|
|
|
Scenario: Detector detects wget piped to sh as MEDIUM
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "wget http://example.com/install.sh | sh"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be MEDIUM
|
|
|
|
Scenario: Detector detects curl piped to sh as MEDIUM
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "curl http://example.com/install.sh | sh"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be MEDIUM
|
|
|
|
Scenario: Detector detects curl piped to bash as MEDIUM
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "curl https://get.example.com | bash"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be MEDIUM
|
|
|
|
Scenario: Detector detects git push force as LOW
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "git push --force origin main"
|
|
Then the command should be detected as dangerous
|
|
And the max danger level should be LOW
|
|
|
|
Scenario: Safe commands pass through without warnings
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "ls -la"
|
|
Then the command should not be detected as dangerous
|
|
|
|
Scenario: Safe commands - echo passes through
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "echo hello world"
|
|
Then the command should not be detected as dangerous
|
|
|
|
Scenario: Safe commands - git status passes through
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "git status"
|
|
Then the command should not be detected as dangerous
|
|
|
|
Scenario: Safe commands - python script passes through
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I check the command "python script.py"
|
|
Then the command should not be detected as dangerous
|
|
|
|
Scenario: check_first returns the first matching warning
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I call check_first on "rm -rf /"
|
|
Then check_first should return a warning
|
|
And the first warning danger level should be CRITICAL
|
|
|
|
Scenario: check_first returns None for safe commands
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I call check_first on "ls -la"
|
|
Then check_first should return None
|
|
|
|
Scenario: check returns all matching warnings
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I call check on "rm -rf /"
|
|
Then check should return at least one warning
|
|
|
|
Scenario: Pattern registry is configurable - add pattern
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I add a custom pattern named "custom_test" with pattern "evil_command" at HIGH level
|
|
And I check the command "evil_command --destroy"
|
|
Then the command should be detected as dangerous
|
|
|
|
Scenario: Pattern registry is configurable - remove pattern
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I remove the pattern named "git_push_force"
|
|
And I check the command "git push --force origin main"
|
|
Then the command should not be detected as dangerous
|
|
|
|
Scenario: Pattern registry is configurable - replace patterns
|
|
Given a DangerousPatternDetector with default patterns
|
|
When I replace all patterns with a single pattern named "only_one" matching "special_cmd" at LOW level
|
|
And I check the command "rm -rf /"
|
|
Then the command should not be detected as dangerous
|
|
When I check the command "special_cmd"
|
|
Then the command should be detected as dangerous
|
|
|
|
Scenario: Detector patterns property returns current registry
|
|
Given a DangerousPatternDetector with default patterns
|
|
Then the detector patterns property should return a tuple
|
|
|
|
# ── ShellSafetyService ───────────────────────────────────────────────────
|
|
|
|
Scenario: ShellSafetyService allows safe commands
|
|
Given a ShellSafetyService with default settings
|
|
When I check the safety of command "ls -la"
|
|
Then the safety check result should be allowed
|
|
And the safety check warning should be None
|
|
|
|
Scenario: ShellSafetyService blocks dangerous commands above block level
|
|
Given a ShellSafetyService with default settings
|
|
When I check the safety of command "rm -rf /"
|
|
Then the safety check result should be blocked
|
|
And the safety check warning should not be None
|
|
|
|
Scenario: ShellSafetyService uses warn_callback when provided
|
|
Given a ShellSafetyService with a warn_callback that returns True
|
|
When I check the safety of command "rm -rf /"
|
|
Then the safety check result should be allowed
|
|
And the warn_callback should have been called
|
|
|
|
Scenario: ShellSafetyService blocks when warn_callback returns False
|
|
Given a ShellSafetyService with a warn_callback that returns False
|
|
When I check the safety of command "rm -rf /"
|
|
Then the safety check result should be blocked
|
|
And the warn_callback should have been called
|
|
|
|
Scenario: ShellSafetyService is_safe returns True for safe commands
|
|
Given a ShellSafetyService with default settings
|
|
When I call is_safe on "echo hello"
|
|
Then is_safe should return True
|
|
|
|
Scenario: ShellSafetyService is_safe returns False for dangerous commands
|
|
Given a ShellSafetyService with default settings
|
|
When I call is_safe on "rm -rf /"
|
|
Then is_safe should return False
|
|
|
|
Scenario: ShellSafetyService exposes detector property
|
|
Given a ShellSafetyService with default settings
|
|
Then the service detector property should be a DangerousPatternDetector
|
|
|
|
Scenario: ShellSafetyService exposes block_level property
|
|
Given a ShellSafetyService with default settings
|
|
Then the service block_level should be MEDIUM
|
|
|
|
Scenario: ShellSafetyService accepts extra_patterns
|
|
Given a ShellSafetyService with an extra pattern "custom_danger" matching "forbidden_cmd" at HIGH level
|
|
When I check the safety of command "forbidden_cmd --run"
|
|
Then the safety check result should be blocked
|
|
|
|
Scenario: SafetyCheckResult repr includes command and allowed status
|
|
Given a ShellSafetyService with default settings
|
|
When I check the safety of command "ls -la"
|
|
Then the safety check result repr should contain "ls -la"
|
|
And the safety check result repr should contain "allowed=True"
|