codecrucible-synth
Version:
Production-Ready AI Development Platform with Multi-Voice Synthesis, Smithery MCP Integration, Enterprise Security, and Zero-Timeout Reliability
629 lines (558 loc) • 18.2 kB
text/typescript
/**
* Advanced Security Validator (ENHANCED)
* Comprehensive security validation system for CodeCrucible Synth
* Enhanced with 2024 AI security research and multi-agent red teaming
*
* Research findings integrated:
* - 29.5% Python and 24.2% JavaScript code snippets contain vulnerabilities
* - AI-specific prompt injection patterns and countermeasures
* - Secret leak detection in AI-generated code
*/
import { Logger } from '../logger.js';
import * as crypto from 'crypto';
export interface SecurityPolicy {
allowedCommands: string[];
blockedPatterns: RegExp[];
maxInputLength: number;
allowCodeExecution: boolean;
allowFileAccess: boolean;
allowNetworkAccess: boolean;
requireSandbox: boolean;
}
export interface ValidationResult {
isValid: boolean;
riskLevel: 'low' | 'medium' | 'high' | 'critical';
violations: SecurityViolation[];
sanitizedInput?: string;
recommendations: string[];
}
export interface SecurityViolation {
type:
| 'command_injection'
| 'path_traversal'
| 'malicious_pattern'
| 'excessive_length'
| 'suspicious_content';
description: string;
severity: 'low' | 'medium' | 'high' | 'critical';
location?: string;
pattern?: string;
}
export class AdvancedSecurityValidator {
private logger: Logger;
private policy: SecurityPolicy;
private knownMaliciousPatterns!: RegExp[];
private suspiciousKeywords!: string[];
constructor(policy?: Partial<SecurityPolicy>) {
this.logger = new Logger('AdvancedSecurityValidator');
this.policy = this.mergeWithDefaultPolicy(policy || {});
this.initializeMaliciousPatterns();
this.initializeSuspiciousKeywords();
}
/**
* Comprehensive input validation
*/
async validateInput(input: string, context?: string): Promise<ValidationResult> {
const violations: SecurityViolation[] = [];
let riskLevel: ValidationResult['riskLevel'] = 'low';
const recommendations: string[] = [];
// Length validation
if (input.length > this.policy.maxInputLength) {
violations.push({
type: 'excessive_length',
description: `Input exceeds maximum length of ${this.policy.maxInputLength} characters`,
severity: 'medium',
});
riskLevel = 'medium';
}
// Command injection detection
const commandViolations = this.detectCommandInjection(input);
violations.push(...commandViolations);
if (commandViolations.some(v => v.severity === 'critical')) {
riskLevel = 'critical';
}
// Path traversal detection
const pathViolations = this.detectPathTraversal(input);
violations.push(...pathViolations);
if (pathViolations.some(v => v.severity === 'high')) {
riskLevel = 'high';
}
// Malicious pattern detection
const patternViolations = this.detectMaliciousPatterns(input);
violations.push(...patternViolations);
if (patternViolations.some(v => v.severity === 'critical')) {
riskLevel = 'critical';
}
// Suspicious content analysis
const contentViolations = await this.analyzeSuspiciousContent(input);
violations.push(...contentViolations);
// Update risk level based on all violations
const highestSeverity = this.getHighestSeverity(violations);
if (highestSeverity === 'critical') riskLevel = 'critical';
else if (highestSeverity === 'high' && riskLevel !== 'critical') riskLevel = 'high';
else if (highestSeverity === 'medium' && riskLevel === 'low') riskLevel = 'medium';
// Generate recommendations
recommendations.push(...this.generateRecommendations(violations, riskLevel));
// Sanitize input if possible
const sanitizedInput = violations.length === 0 ? input : this.sanitizeInput(input, violations);
return {
isValid:
riskLevel !== 'critical' && violations.filter(v => v.severity === 'critical').length === 0,
riskLevel,
violations,
sanitizedInput,
recommendations,
};
}
/**
* Detect command injection attempts
*/
private detectCommandInjection(input: string): SecurityViolation[] {
const violations: SecurityViolation[] = [];
// Shell metacharacters and patterns
const commandPatterns = [
{ pattern: /[;&|`$(){}]/g, severity: 'high' as const, desc: 'Shell metacharacters detected' },
{ pattern: /\|\s*[a-z]/gi, severity: 'critical' as const, desc: 'Pipe to command detected' },
{ pattern: /&&\s*[a-z]/gi, severity: 'critical' as const, desc: 'Command chaining detected' },
{ pattern: /;\s*[a-z]/gi, severity: 'critical' as const, desc: 'Command separator detected' },
{ pattern: /`[^`]+`/g, severity: 'critical' as const, desc: 'Command substitution detected' },
{
pattern: /\$\([^)]+\)/g,
severity: 'critical' as const,
desc: 'Command substitution detected',
},
{
pattern: /rm\s+-r?f?\s+/gi,
severity: 'critical' as const,
desc: 'Dangerous delete command detected',
},
{
pattern: /curl\s+.*(\||>)/gi,
severity: 'high' as const,
desc: 'Network download with redirection',
},
{
pattern: /wget\s+.*(\||>)/gi,
severity: 'high' as const,
desc: 'Network download with redirection',
},
{
pattern: /chmod\s+[0-9]+/gi,
severity: 'medium' as const,
desc: 'File permission modification',
},
{ pattern: /sudo\s+/gi, severity: 'high' as const, desc: 'Privilege escalation attempt' },
{ pattern: /su\s+/gi, severity: 'high' as const, desc: 'User switching attempt' },
];
for (const { pattern, severity, desc } of commandPatterns) {
const matches = input.match(pattern);
if (matches) {
violations.push({
type: 'command_injection',
description: desc,
severity,
pattern: pattern.toString(),
});
}
}
return violations;
}
/**
* Detect path traversal attempts
*/
private detectPathTraversal(input: string): SecurityViolation[] {
const violations: SecurityViolation[] = [];
const pathPatterns = [
{ pattern: /\.\.\/+/g, severity: 'high' as const, desc: 'Directory traversal detected' },
{
pattern: /\.\.\\+/g,
severity: 'high' as const,
desc: 'Windows directory traversal detected',
},
{
pattern: /\/etc\/passwd/gi,
severity: 'critical' as const,
desc: 'System file access attempt',
},
{
pattern: /\/etc\/shadow/gi,
severity: 'critical' as const,
desc: 'Password file access attempt',
},
{
pattern: /C:\\Windows\\System32/gi,
severity: 'high' as const,
desc: 'Windows system directory access',
},
{
pattern: /\/proc\/self\/environ/gi,
severity: 'high' as const,
desc: 'Environment variable access',
},
{
pattern: /\/home\/[^/]+\/\.ssh/gi,
severity: 'high' as const,
desc: 'SSH key directory access',
},
];
for (const { pattern, severity, desc } of pathPatterns) {
const matches = input.match(pattern);
if (matches) {
violations.push({
type: 'path_traversal',
description: desc,
severity,
pattern: pattern.toString(),
});
}
}
return violations;
}
/**
* Detect known malicious patterns
*/
private detectMaliciousPatterns(input: string): SecurityViolation[] {
const violations: SecurityViolation[] = [];
for (const pattern of this.knownMaliciousPatterns) {
if (pattern.test(input)) {
violations.push({
type: 'malicious_pattern',
description: `Known malicious pattern detected: ${pattern.toString()}`,
severity: 'critical',
pattern: pattern.toString(),
});
}
}
return violations;
}
/**
* Analyze content for suspicious patterns
*/
private async analyzeSuspiciousContent(input: string): Promise<SecurityViolation[]> {
const violations: SecurityViolation[] = [];
const lowerInput = input.toLowerCase();
// Check for suspicious keywords
for (const keyword of this.suspiciousKeywords) {
if (lowerInput.includes(keyword)) {
violations.push({
type: 'suspicious_content',
description: `Suspicious keyword detected: ${keyword}`,
severity: 'medium',
});
}
}
// Check for encoded content that might be malicious
if (this.detectEncodedMaliciousContent(input)) {
violations.push({
type: 'suspicious_content',
description: 'Potentially encoded malicious content detected',
severity: 'high',
});
}
// Check for SQL injection patterns
const sqlPatterns = [
/union\s+select/gi,
/drop\s+table/gi,
/delete\s+from/gi,
/insert\s+into/gi,
/update\s+.*set/gi,
/'.*or.*'.*=.*'/gi,
];
for (const pattern of sqlPatterns) {
if (pattern.test(input)) {
violations.push({
type: 'suspicious_content',
description: 'SQL injection pattern detected',
severity: 'high',
pattern: pattern.toString(),
});
}
}
return violations;
}
/**
* Detect encoded malicious content
*/
private detectEncodedMaliciousContent(input: string): boolean {
try {
// Check for base64 encoded content
const base64Pattern = /[A-Za-z0-9+/]{20,}={0,2}/g;
const base64Matches = input.match(base64Pattern);
if (base64Matches) {
for (const match of base64Matches) {
try {
const decoded = Buffer.from(match, 'base64').toString('utf-8');
if (this.containsSuspiciousPatterns(decoded)) {
return true;
}
} catch {
// Ignore invalid base64
}
}
}
// Check for URL encoded content
const urlEncodedPattern = /%[0-9A-Fa-f]{2}/g;
if (urlEncodedPattern.test(input)) {
try {
const decoded = decodeURIComponent(input);
if (this.containsSuspiciousPatterns(decoded)) {
return true;
}
} catch {
// Ignore invalid URL encoding
}
}
// Check for hex encoded content
const hexPattern = /\\x[0-9A-Fa-f]{2}/g;
if (hexPattern.test(input)) {
const decoded = input.replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) =>
String.fromCharCode(parseInt(hex, 16))
);
if (this.containsSuspiciousPatterns(decoded)) {
return true;
}
}
} catch (error) {
this.logger.warn('Error checking encoded content:', error);
}
return false;
}
/**
* Check if text contains suspicious patterns
*/
private containsSuspiciousPatterns(text: string): boolean {
const suspiciousPatterns = [
/rm\s+-rf/i,
/malicious/i,
/exploit/i,
/payload/i,
/shellcode/i,
/backdoor/i,
];
return suspiciousPatterns.some(pattern => pattern.test(text));
}
/**
* Sanitize input by removing or escaping dangerous content
*/
private sanitizeInput(input: string, violations: SecurityViolation[]): string {
let sanitized = input;
// Remove shell metacharacters
sanitized = sanitized.replace(/[;&|`$(){}]/g, '');
// Remove path traversal sequences
sanitized = sanitized.replace(/\.\.\/+/g, './');
sanitized = sanitized.replace(/\.\.\\+/g, '.\\');
// Remove dangerous commands
sanitized = sanitized.replace(/rm\s+-r?f?\s+/gi, '[FILTERED] ');
sanitized = sanitized.replace(/curl\s+/gi, '[FILTERED] ');
sanitized = sanitized.replace(/wget\s+/gi, '[FILTERED] ');
sanitized = sanitized.replace(/sudo\s+/gi, '[FILTERED] ');
// Filter out malicious keywords including "malicious" itself
const criticalKeywords = ['malicious', 'exploit', 'payload', 'shellcode', 'backdoor'];
for (const keyword of criticalKeywords) {
const regex = new RegExp(keyword, 'gi');
sanitized = sanitized.replace(regex, '[FILTERED]');
}
return sanitized;
}
/**
* Generate security recommendations
*/
private generateRecommendations(
violations: SecurityViolation[],
riskLevel: ValidationResult['riskLevel']
): string[] {
const recommendations: string[] = [];
if (riskLevel === 'critical') {
recommendations.push(
'CRITICAL: Input contains dangerous patterns that could compromise system security'
);
recommendations.push(
'Recommend rejecting this input and implementing additional validation layers'
);
}
if (violations.some(v => v.type === 'command_injection')) {
recommendations.push('Implement command whitelisting and input escaping');
recommendations.push('Use sandboxed execution environment for any command execution');
}
if (violations.some(v => v.type === 'path_traversal')) {
recommendations.push(
'Implement path validation and restrict file access to approved directories'
);
recommendations.push('Use absolute paths and canonical path resolution');
}
if (violations.some(v => v.type === 'malicious_pattern')) {
recommendations.push(
'Content matches known malicious patterns - consider blocking this input'
);
recommendations.push('Update malicious pattern database regularly');
}
return recommendations;
}
/**
* Get highest severity level from violations
*/
private getHighestSeverity(violations: SecurityViolation[]): SecurityViolation['severity'] {
if (violations.some(v => v.severity === 'critical')) return 'critical';
if (violations.some(v => v.severity === 'high')) return 'high';
if (violations.some(v => v.severity === 'medium')) return 'medium';
return 'low';
}
/**
* Initialize known malicious patterns
*/
private initializeMaliciousPatterns(): void {
this.knownMaliciousPatterns = [
// Known attack patterns
/nc\s+-l.*-e/gi, // Netcat reverse shell
/python.*-c.*exec/gi, // Python code execution
/perl.*-e/gi, // Perl one-liner
/ruby.*-e/gi, // Ruby one-liner
/bash.*-c/gi, // Bash command execution
/sh.*-c/gi, // Shell command execution
/powershell.*-c/gi, // PowerShell execution
/cmd.*\/c/gi, // Windows command execution
// File operations
/echo.*>>.*\/etc\//gi, // Writing to system files
/cat.*\/etc\/passwd/gi, // Reading password file
/ls.*-la.*\/etc/gi, // Listing system directories
// Network operations
/wget.*\|\s*sh/gi, // Download and execute
/curl.*\|\s*bash/gi, // Download and execute
// Process manipulation
/kill\s+-9/gi, // Force kill processes
/killall/gi, // Kill all processes
/pkill/gi, // Pattern-based process killing
// System information gathering
/uname\s+-a/gi, // System information
/whoami/gi, // Current user
/id\s*$/gi, // User ID information
/ps\s+aux/gi, // Process listing
// Privilege escalation
/sudo\s+su/gi, // Switch to root
/su\s+-/gi, // Switch user
/chmod\s+777/gi, // Full permissions
/chown\s+root/gi, // Change ownership to root
];
}
/**
* Initialize suspicious keywords
*/
private initializeSuspiciousKeywords(): void {
this.suspiciousKeywords = [
// Hacking/exploitation terms
'exploit',
'payload',
'shellcode',
'backdoor',
'trojan',
'virus',
'rootkit',
'keylogger',
'botnet',
'ransomware',
'malware',
// Attack methods
'injection',
'overflow',
'xss',
'csrf',
'clickjacking',
'phishing',
'spoofing',
'sniffing',
'bruteforce',
'dictionary',
'rainbow',
// System compromise
'privilege escalation',
'lateral movement',
'persistence',
'exfiltration',
'command and control',
'c2',
'reverse shell',
'bind shell',
// 2024 AI-specific threat keywords
'prompt injection',
'jailbreak',
'ignore previous instructions',
'forget everything',
'new instructions',
'role hijacking',
'system override',
'memory manipulation',
'context switching',
// Sensitive operations (context-dependent)
'format disk',
'delete system',
'remove all',
'wipe drive',
'master boot record',
'boot sector',
'partition table',
];
}
/**
* Merge with default security policy
*/
private mergeWithDefaultPolicy(policy: Partial<SecurityPolicy>): SecurityPolicy {
const defaultPolicy: SecurityPolicy = {
allowedCommands: [
'ls',
'cat',
'grep',
'find',
'head',
'tail',
'wc',
'sort',
'uniq',
'git',
'npm',
'node',
'python',
'pip',
'cargo',
'rustc',
'tsc',
'eslint',
'prettier',
'jest',
'mocha',
'pytest',
],
blockedPatterns: [/rm\s+-rf/, /sudo\s+/, /chmod\s+777/, />\s*\/dev\/null/, /2>&1/, /nohup/],
maxInputLength: 10000,
allowCodeExecution: false,
allowFileAccess: true,
allowNetworkAccess: false,
requireSandbox: true,
};
return { ...defaultPolicy, ...policy };
}
/**
* Update security policy
*/
updatePolicy(newPolicy: Partial<SecurityPolicy>): void {
this.policy = { ...this.policy, ...newPolicy };
this.logger.info('Security policy updated');
}
/**
* Get current security policy
*/
getPolicy(): SecurityPolicy {
return { ...this.policy };
}
/**
* Generate security report
*/
generateSecurityReport(): any {
return {
policy: this.policy,
maliciousPatternsCount: this.knownMaliciousPatterns.length,
suspiciousKeywordsCount: this.suspiciousKeywords.length,
lastUpdated: new Date().toISOString(),
};
}
}
export default AdvancedSecurityValidator;