Add security and best_practices validators

This commit is contained in:
2026-01-29 21:26:39 +00:00
parent 12f14232d9
commit 209b5b3477

View File

@@ -1,64 +1,35 @@
"""Security vulnerability scanning module."""
"""Security vulnerability scanning."""
from typing import List, Optional
from ..models import Rule, Finding
class SecurityValidator:
"""Scans shell scripts for security vulnerabilities."""
DEFAULT_PATTERNS = [
Rule(
id="SECURITY001",
name="Unquoted variable",
pattern=r"(?<![\"'])(\$[a-zA-Z_][a-zA-Z0-9_]*)(?![\"'])",
severity="high",
id="SECURITY001", name="Unquoted variable",
pattern=r"(?<![\"])(\$[a-zA-Z_][a-zA-Z0-9_]*)(?![\"])", severity="high",
message="Unquoted variable can cause word splitting and glob expansion",
suggestion="Always quote variables: \"$VAR\" instead of $VAR",
),
Rule(
id="SECURITY002",
name="Command substitution in variable context",
pattern=r"\$\([^)]+\)",
severity="high",
id="SECURITY002", name="Command substitution",
pattern=r"\$\([^)]+\)", severity="high",
message="Command substitution can be exploited if output contains special characters",
suggestion="Validate and sanitize command substitution output",
),
Rule(
id="SECURITY003",
name="Path traversal pattern",
pattern=r"\$\w+/\.\./|\$\w+/\.\.\$",
severity="high",
id="SECURITY003", name="Path traversal pattern",
pattern=r"\$\w+/\.\./|\$\w+/\.\.\$", severity="high",
message="Path traversal detected with variable - potential security vulnerability",
suggestion="Validate and normalize paths. Use realpath() or similar to resolve paths.",
),
Rule(
id="SECURITY004",
name="Shell metacharacter injection",
pattern=r"[;&|\`$!#()*?<>{}]\s*\$\w+",
severity="high",
message="Shell metacharacters followed by variable can lead to injection",
suggestion="Sanitize variables to remove or escape shell metacharacters",
),
Rule(
id="SECURITY005",
name="exec with shell variable",
pattern=r"exec\s+.*\$\w+",
severity="high",
message="exec with variable can be exploited",
suggestion="Avoid using variables with exec. Use explicit command paths.",
suggestion="Validate and normalize paths. Use realpath() or similar.",
),
]
def __init__(self, custom_rules: Optional[List[Rule]] = None):
"""Initialize the security 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 security vulnerabilities."""
def validate(self, content, line_number=None):
findings = []
for rule in self.rules:
if not rule.enabled:
@@ -68,17 +39,3 @@ class SecurityValidator:
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 security vulnerabilities."""
return self.validate(command)