mirror of
https://github.com/SuperClaude-Org/SuperClaude_Framework.git
synced 2025-12-29 16:16:08 +00:00
Add validators package with 6 specialized validators: - base.py: Abstract base validator with common patterns - context_contract.py: PM mode context validation - dep_sanity.py: Dependency consistency checks - runtime_policy.py: Runtime policy enforcement - security_roughcheck.py: Security vulnerability scanning - test_runner.py: Automated test execution validation Supports validation gates for quality assurance and risk mitigation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
145 lines
5.0 KiB
Python
145 lines
5.0 KiB
Python
"""Security Roughcheck Validator
|
|
|
|
Detects common security anti-patterns:
|
|
- Hardcoded secrets (API keys, tokens, passwords)
|
|
- .env file creation in commits
|
|
- Exposed credentials in code
|
|
- Unsafe practices
|
|
"""
|
|
|
|
from typing import Dict, Any, List
|
|
import re
|
|
from pathlib import Path
|
|
|
|
from .base import Validator, ValidationResult
|
|
|
|
|
|
class SecurityRoughcheckValidator(Validator):
|
|
"""Validates against common security issues"""
|
|
|
|
# Secret detection patterns
|
|
SECRET_PATTERNS = [
|
|
(r'sk_live_[a-zA-Z0-9]{24,}', 'Stripe live secret key'),
|
|
(r'pk_live_[a-zA-Z0-9]{24,}', 'Stripe live publishable key'),
|
|
(r'sk_test_[a-zA-Z0-9]{24,}', 'Stripe test secret key'),
|
|
(r'SUPABASE_SERVICE_ROLE_KEY\s*=\s*[\'"]eyJ', 'Supabase service role key'),
|
|
(r'SUPABASE_ANON_KEY\s*=\s*[\'"]eyJ', 'Supabase anon key'),
|
|
(r'OPENAI_API_KEY\s*=\s*[\'"]sk-', 'OpenAI API key'),
|
|
(r'TWILIO_AUTH_TOKEN\s*=\s*[\'"][a-f0-9]{32}', 'Twilio auth token'),
|
|
(r'INFISICAL_TOKEN\s*=\s*[\'"]st\.', 'Infisical token'),
|
|
(r'DATABASE_URL\s*=\s*[\'"]postgres.*password', 'Database password in URL'),
|
|
(r'AWS_SECRET_ACCESS_KEY\s*=\s*[\'"][\w/+=]{40}', 'AWS secret access key'),
|
|
(r'GITHUB_TOKEN\s*=\s*[\'"]gh[ps]_[a-zA-Z0-9]{36}', 'GitHub token'),
|
|
]
|
|
|
|
# Unsafe patterns
|
|
UNSAFE_PATTERNS = [
|
|
(r'eval\s*\(', 'Use of eval() function'),
|
|
(r'exec\s*\(', 'Use of exec() function'),
|
|
(r'__import__\s*\(', 'Dynamic import with __import__'),
|
|
(r'shell=True', 'Shell command execution'),
|
|
(r'pickle\.loads?\s*\(', 'Unsafe pickle deserialization'),
|
|
]
|
|
|
|
def __init__(self):
|
|
super().__init__("Security Roughcheck")
|
|
|
|
def validate(self, context: Dict[str, Any]) -> ValidationResult:
|
|
"""
|
|
Validate security.
|
|
|
|
Context should contain:
|
|
- changes: File changes
|
|
"""
|
|
changes = context.get("changes", {})
|
|
if not changes:
|
|
return self._pass("No changes to validate")
|
|
|
|
critical_issues = []
|
|
warnings = []
|
|
|
|
for file_path, content in changes.items():
|
|
# Check 1: .env file creation
|
|
if ".env" in Path(file_path).name:
|
|
critical_issues.append(f"❌ CRITICAL: .env file detected: {file_path}")
|
|
|
|
# Check 2: Hardcoded secrets
|
|
for pattern, description in self.SECRET_PATTERNS:
|
|
matches = re.findall(pattern, content)
|
|
if matches:
|
|
critical_issues.append(
|
|
f"❌ CRITICAL: {description} detected in {file_path}"
|
|
)
|
|
|
|
# Check 3: Unsafe patterns
|
|
for pattern, description in self.UNSAFE_PATTERNS:
|
|
matches = re.findall(pattern, content)
|
|
if matches:
|
|
warnings.append(f"⚠️ {description} in {file_path}")
|
|
|
|
# Check 4: Exposed API endpoints without auth
|
|
if self._looks_like_api_route(file_path):
|
|
if not self._has_auth_check(content):
|
|
warnings.append(
|
|
f"⚠️ Possible unauthenticated API endpoint in {file_path}"
|
|
)
|
|
|
|
# Generate suggestions
|
|
suggestions = []
|
|
if critical_issues:
|
|
suggestions.extend([
|
|
"Remove hardcoded secrets immediately",
|
|
"Use environment variables or secret management (Infisical)",
|
|
"Never commit .env files - add to .gitignore"
|
|
])
|
|
|
|
if warnings:
|
|
suggestions.extend([
|
|
"Review security warnings carefully",
|
|
"Consider safer alternatives where possible"
|
|
])
|
|
|
|
# Return result
|
|
if critical_issues:
|
|
return self._fail(
|
|
f"CRITICAL security issues detected ({len(critical_issues)} issues)",
|
|
details={
|
|
"critical": critical_issues,
|
|
"warnings": warnings
|
|
},
|
|
suggestions=suggestions
|
|
)
|
|
|
|
if warnings:
|
|
return self._warning(
|
|
f"Security warnings detected ({len(warnings)} warnings)",
|
|
details={"warnings": warnings},
|
|
suggestions=suggestions
|
|
)
|
|
|
|
return self._pass("No security issues detected")
|
|
|
|
def _looks_like_api_route(self, file_path: str) -> bool:
|
|
"""Check if file looks like an API route"""
|
|
api_indicators = [
|
|
"/api/",
|
|
"/routes/",
|
|
"/endpoints/",
|
|
".route.",
|
|
".api.",
|
|
]
|
|
return any(indicator in file_path.lower() for indicator in api_indicators)
|
|
|
|
def _has_auth_check(self, content: str) -> bool:
|
|
"""Check if content has authentication checks"""
|
|
auth_patterns = [
|
|
r'@auth', # Decorator
|
|
r'authenticate',
|
|
r'authorize',
|
|
r'requireAuth',
|
|
r'verifyToken',
|
|
r'checkAuth',
|
|
r'isAuthenticated',
|
|
]
|
|
return any(re.search(pattern, content, re.IGNORECASE) for pattern in auth_patterns)
|