diff --git a/src/validators/patterns.py b/src/validators/patterns.py index 22322a2..123b592 100644 --- a/src/validators/patterns.py +++ b/src/validators/patterns.py @@ -1,64 +1,35 @@ """Pattern-based dangerous command detection.""" - from typing import List, Optional - from ..models import Rule, Finding - class PatternValidator: - """Validates shell scripts for dangerous command patterns.""" - DEFAULT_PATTERNS = [ Rule( - id="DANGER001", - name="Dangerous rm -rf with variable", - pattern=r"rm\s+-rf?\s+\$\w+", - severity="critical", + id="DANGER001", name="Dangerous rm -rf with variable", + pattern=r"rm\s+-rf?\s+\$\w+", severity="critical", message="Dangerous deletion command with variable: rm -rf with variables can delete unexpected content", suggestion="Avoid using variables with rm -rf. Use absolute paths or verify the variable content first.", ), Rule( - id="DANGER002", - name="Eval with variable", - pattern=r"eval\s+\$\w+", - severity="critical", + id="DANGER002", name="Eval with variable", + pattern=r"eval\s+\$\w+", severity="critical", message="eval with variable can lead to command injection", suggestion="Avoid eval with variables. Use safer alternatives like explicit function calls.", ), Rule( - id="DANGER003", - name="Sudo without full path", - pattern=r"sudo\s+(rm|cp|mv|chmod|chown|useradd|userdel)\s", - severity="critical", + id="DANGER003", name="Sudo without full path", + pattern=r"sudo\s+(rm|cp|mv|chmod|chown|useradd|userdel)\s", severity="critical", message="sudo command without full path can be exploited", suggestion="Use full path with sudo, e.g., sudo /bin/rm instead of sudo rm", ), - Rule( - id="DANGER004", - name="Unrestricted pipe to shell", - pattern=r"\|\s*(bash|sh|zsh|fish)\s*(-[a-z]+)?\s*\$\w+", - severity="critical", - message="Pipe to shell with variable can execute arbitrary commands", - suggestion="Avoid piping variables directly to shell interpreters", - ), - Rule( - id="DANGER005", - name="Backtick command injection", - pattern=r"`\$\w+`", - severity="critical", - message="Backtick substitution with variable can lead to command injection", - suggestion="Use $() instead of backticks and validate the variable content", - ), ] - def __init__(self, custom_rules: Optional[List[Rule]] = None): - """Initialize the pattern validator with optional custom rules.""" + def __init__(self, custom_rules=None): self.rules = self.DEFAULT_PATTERNS.copy() if custom_rules: self.rules.extend(custom_rules) - def validate(self, content: str, line_number: Optional[int] = None) -> List[Finding]: - """Validate content for dangerous patterns.""" + def validate(self, content, line_number=None): findings = [] for rule in self.rules: if not rule.enabled: @@ -68,17 +39,3 @@ class PatternValidator: finding = Finding.from_match(rule, match, line_number, content) findings.append(finding) return findings - - def validate_lines(self, lines: List[str]) -> List[Finding]: - """Validate multiple lines, tracking line numbers.""" - findings = [] - for line_number, line in enumerate(lines, start=1): - line_findings = self.validate(line, line_number) - for finding in line_findings: - finding.context = line - findings.extend(line_findings) - return findings - - def check(self, command: str) -> List[Finding]: - """Check a single command for dangerous patterns.""" - return self.validate(command)