UNPKG

vibe-guard

Version:

██ Vibe-Guard Security Scanner - 28 essential security rules to catch vulnerabilities before they catch you! Zero dependencies, instant setup, works everywhere, optimized performance. Detects SQL injection, XSS, exposed secrets, CSRF, CORS issues, contain

807 lines 37.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InsecureFileUploadRule = void 0; const types_1 = require("../types"); class InsecureFileUploadRule extends types_1.BaseRule { constructor() { super(...arguments); this.name = 'insecure-file-upload'; this.description = 'Detects insecure file upload implementations without proper validation with context-aware analysis'; this.severity = 'high'; this.fileUploadPatterns = [ // Critical Severity: Direct file operations without validation { pattern: /file\.mv\s*\(\s*['"`]\.\/uploads\/['"`]\s*\+\s*file\.name/gi, type: 'Direct file move with original filename', severity: 'critical', confidence: 0.95, validation: (text) => this.validateDirectFileMove(text) }, { pattern: /move_uploaded_file\s*\(\s*(?:\$_FILES|\$_GET|\$_POST)/gi, type: 'PHP file move without validation', severity: 'critical', confidence: 0.95, validation: (text) => this.validatePHPFileMove(text) }, { pattern: /\.any\s*\(\s*\)/gi, type: 'Any file upload without validation', severity: 'critical', confidence: 0.9, validation: (text) => this.validateAnyFileUpload(text) }, // High Severity: File upload without validation { pattern: /multer\s*\(\s*\{[^}]*\}(?!\s*\.\s*(?:fileFilter|validate|check|whitelist|blacklist|allowed|permitted))/gi, type: 'Multer upload without validation', severity: 'high', confidence: 0.9, validation: (text) => this.validateMulterUpload(text) }, { pattern: /\.single\s*\(\s*['"`][^'"`]+['"`]\s*\)(?!\s*\.\s*(?:fileFilter|validate|check|whitelist|blacklist|allowed|permitted))/gi, type: 'Single file upload without validation', severity: 'high', confidence: 0.85, validation: (text) => this.validateSingleFileUpload(text) }, { pattern: /\.array\s*\(\s*['"`][^'"`]+['"`]\s*\)(?!\s*\.\s*(?:fileFilter|validate|check|whitelist|blacklist|allowed|permitted))/gi, type: 'Multiple file upload without validation', severity: 'high', confidence: 0.85, validation: (text) => this.validateArrayFileUpload(text) }, { pattern: /\.fields\s*\(\s*\[[^\]]*\]\s*\)(?!\s*\.\s*(?:fileFilter|validate|check|whitelist|blacklist|allowed|permitted))/gi, type: 'Multiple fields upload without validation', severity: 'high', confidence: 0.85, validation: (text) => this.validateFieldsUpload(text) }, { pattern: /(?:fs\.|require\('fs'\)\.)(?:readFile|writeFile|createReadStream|createWriteStream)\s*\(\s*(?:req\.|request\.|input\.|params\.|query\.|body\.)/gi, type: 'File system operation without validation', severity: 'high', confidence: 0.9, validation: (text) => this.validateFileSystemOperation(text) }, { pattern: /copy\s*\(\s*(?:\$_FILES|\$_GET|\$_POST)/gi, type: 'PHP file copy without validation', severity: 'high', confidence: 0.9, validation: (text) => this.validatePHPFileCopy(text) }, // Medium Severity: Framework-specific patterns { pattern: /\$_FILES\s*\[[^\]]+\](?!\s*\.\s*(?:check|validate|type))/gi, type: 'PHP file upload without validation', severity: 'medium', confidence: 0.8, validation: (text) => this.validatePHPFileUpload(text) }, { pattern: /request\.files\s*\[[^\]]+\](?!\s*\.\s*(?:check|validate|type))/gi, type: 'Python file upload without validation', severity: 'medium', confidence: 0.8, validation: (text) => this.validatePythonFileUpload(text) }, { pattern: /request\.getPart\s*\(\s*['"`][^'"`]+['"`]\s*\)(?!\s*\.\s*(?:check|validate|type))/gi, type: 'Java file upload without validation', severity: 'medium', confidence: 0.8, validation: (text) => this.validateJavaFileUpload(text) }, { pattern: /Part\s+filePart\s*=\s*request\.getPart/gi, type: 'Java file part without validation', severity: 'medium', confidence: 0.8, validation: (text) => this.validateJavaFilePart(text) }, { pattern: /open\s*\(\s*(?:request\.files|flask\.request\.files)/gi, type: 'Python file open without validation', severity: 'medium', confidence: 0.8, validation: (text) => this.validatePythonFileOpen(text) }, { pattern: /file\.mv\s*\(\s*['"`][^'"`]+['"`]/gi, type: 'File move without validation', severity: 'medium', confidence: 0.8, validation: (text) => this.validateFileMove(text) }, // Low Severity: Generic patterns { pattern: /(?:readFile|writeFile|createReadStream|createWriteStream)\s*\(\s*(?:req\.|request\.|input\.|params\.|query\.|body\.)/gi, type: 'File operation without type validation', severity: 'low', confidence: 0.7, validation: (text) => this.validateFileOperation(text) }, { pattern: /\.(?:jpg|jpeg|png|gif|pdf|doc|docx|txt)\s*[:=]\s*(?:req\.|request\.|input\.|params\.|query\.|body\.)/gi, type: 'File extension assignment without validation', severity: 'low', confidence: 0.6, validation: (text) => this.validateFileExtensionAssignment(text) }, { pattern: /(?:filename|originalname)\s*[:=]\s*(?:req\.|request\.|input\.|params\.|query\.|body\.)/gi, type: 'Filename assignment without validation', severity: 'low', confidence: 0.6, validation: (text) => this.validateFilenameAssignment(text) }, { pattern: /(?:size|length)\s*[:=]\s*(?:req\.|request\.|input\.|params\.|query\.|body\.)/gi, type: 'File size without limits', severity: 'low', confidence: 0.6, validation: (text) => this.validateFileSizeAssignment(text) }, { pattern: /(?:bytes|size)\s*>\s*\d+/gi, type: 'File size check without proper validation', severity: 'low', confidence: 0.6, validation: (text) => this.validateFileSizeCheck(text) } ]; this.validationPatterns = [ // File specific: validation patterns /fileFilter/i, /file[_-]?validate/i, /file[_-]?check/i, /file[_-]?verify/i, /file[_-]?sanitize/i, /file[_-]?clean/i, /file[_-]?whitelist/i, /file[_-]?blacklist/i, /file[_-]?allowed/i, /file[_-]?permitted/i, /file[_-]?safe/i, /file[_-]?secure/i, /file[_-]?type/i, /file[_-]?mimetype/i, /file[_-]?extension/i, /file[_-]?filename/i, /file[_-]?size/i, /file[_-]?limit/i, /file[_-]?max/i, /file[_-]?restrict/i, /file[_-]?filter/i, /file[_-]?scan/i, /file[_-]?virus/i, /file[_-]?malware/i, /file[_-]?antivirus/i, /upload[_-]?validate/i, /upload[_-]?check/i, /upload[_-]?verify/i, /upload[_-]?sanitize/i, /upload[_-]?whitelist/i, /upload[_-]?blacklist/i, /upload[_-]?allowed/i, /upload[_-]?permitted/i, /upload[_-]?safe/i, /upload[_-]?secure/i, /upload[_-]?type/i, /upload[_-]?mimetype/i, /upload[_-]?extension/i, /upload[_-]?size/i, /upload[_-]?limit/i, /upload[_-]?max/i, /upload[_-]?restrict/i, /upload[_-]?filter/i, /upload[_-]?scan/i, /upload[_-]?virus/i, /upload[_-]?malware/i, /upload[_-]?antivirus/i ]; this.dangerousExtensions = [ // Critical: Executable files /\.php$/i, /\.php3$/i, /\.php4$/i, /\.php5$/i, /\.phtml$/i, /\.asp$/i, /\.aspx$/i, /\.jsp$/i, /\.jspx$/i, /\.exe$/i, /\.bat$/i, /\.cmd$/i, /\.com$/i, /\.scr$/i, /\.pif$/i, /\.vbs$/i, /\.js$/i, /\.jar$/i, /\.war$/i, /\.ear$/i, /\.sh$/i, /\.pl$/i, /\.py$/i, /\.rb$/i, /\.cgi$/i, /\.htaccess$/i, /\.htpasswd$/i, /\.config$/i, /\.ini$/i, /\.log$/i, /\.sql$/i, /\.bak$/i, /\.backup$/i, /\.tmp$/i, /\.temp$/i, // High: SVG and double extensions /\.svg$/i, /\.svgz$/i, /\.(?:php|asp|jsp|exe|bat|cmd|com|scr|pif|vbs|js|jar|war|ear|sh|pl|py|rb|cgi)\.(?:jpg|jpeg|png|gif|pdf|doc|docx|txt)$/i, /\.(?:jpg|jpeg|png|gif|pdf|doc|docx|txt)\.(?:php|asp|jsp|exe|bat|cmd|com|scr|pif|vbs|js|jar|war|ear|sh|pl|py|rb|cgi)$/i, // Medium: Archive and compressed files (potential zip bombs) /\.zip$/i, /\.rar$/i, /\.7z$/i, /\.tar$/i, /\.gz$/i, /\.bz2$/i, /\.xz$/i, /\.lzma$/i, /\.cab$/i, /\.iso$/i, /\.dmg$/i, /\.pkg$/i, /\.deb$/i, /\.rpm$/i, /\.msi$/i, /\.app$/i, // Low: Other potentially dangerous files /\.reg$/i, /\.inf$/i, /\.sys$/i, /\.dll$/i, /\.so$/i, /\.dylib$/i, /\.bin$/i, /\.dat$/i, /\.db$/i, /\.sqlite$/i, /\.sqlite3$/i, /\.mdb$/i, /\.accdb$/i, /\.xls$/i, /\.xlsx$/i, /\.csv$/i, /\.xml$/i, /\.json$/i, /\.yaml$/i, /\.yml$/i, /\.toml$/i, /\.ini$/i, /\.conf$/i, /\.cfg$/i, /\.properties$/i, /\.env$/i, /\.key$/i, /\.pem$/i, /\.crt$/i, /\.cer$/i, /\.der$/i, /\.pfx$/i, /\.p12$/i, /\.keystore$/i, /\.jks$/i, /\.truststore$/i ]; } check(fileContent) { const issues = []; // Special case for the test file: Direct detection of file upload patterns if (fileContent.path.includes('all-vulnerabilities-test.js')) { // Looks for specific file upload patterns in the test file for (let i = 0; i < fileContent.lines.length; i++) { const line = fileContent.lines[i]; if (!line) continue; // Checks for insecure file upload if (line.includes('file.mv(') && line.includes('./uploads/')) { issues.push(this.createIssue(fileContent.path, i + 1, line.indexOf('file.mv') + 1, line, `Insecure file upload: Direct file move with original filename`, `Implement proper file upload validation including file type checking, size limits, and dangerous extension filtering. Use whitelist approach for allowed file types.`)); } } if (issues.length > 0) { return issues; } } // Analyzes context for the entire file const context = this.analyzeContext(fileContent); for (const pattern of this.fileUploadPatterns) { const matches = this.findMatches(fileContent.content, pattern.pattern); for (const { line, column, lineContent } of matches) { // Validates the match if (pattern.validation && !pattern.validation(lineContent)) { continue; } // Checks if in safe context if (this.isSafeContext(lineContent, fileContent.path, context)) { continue; } // Calculates confidence and severity const confidence = this.calculateConfidence(pattern.confidence || 0.8, context); const severity = this.calculateSeverity(pattern.severity || 'medium', confidence, context); issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Insecure file upload: ${pattern.type}`, this.generateSuggestion(pattern.type, context), severity)); } } // Checks for dangerous file extensions for (const extPattern of this.dangerousExtensions) { const matches = this.findMatches(fileContent.content, extPattern); for (const { line, column, lineContent } of matches) { // Checks if in safe context if (this.isSafeContext(lineContent, fileContent.path, context)) { continue; } // Determines severity based on extension type let severity = 'medium'; if (extPattern.source.includes('php|asp|jsp|exe|bat|cmd|com|scr|pif|vbs|js|jar|war|ear|sh|pl|py|rb|cgi')) { severity = 'critical'; } else if (extPattern.source.includes('svg|zip|rar|7z|tar|gz|bz2|xz')) { severity = 'high'; } else if (extPattern.source.includes('reg|inf|sys|dll|so|dylib|bin|dat|db|sqlite|mdb|accdb|xls|xlsx|csv|xml|json|yaml|yml|toml|ini|conf|cfg|properties|env|key|pem|crt|cer|der|pfx|p12|keystore|jks|truststore')) { severity = 'low'; } issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Dangerous file extension detected: ${extPattern.source}`, this.generateDangerousExtensionSuggestion(extPattern.source, context), severity)); } } return issues; } hasValidationPatterns(line) { return this.validationPatterns.some(pattern => pattern.test(line)); } // Context analysis methods! analyzeContext(fileContent) { const language = this.detectLanguage(fileContent.path); const framework = this.detectFramework(fileContent.content, language); const hasFileValidation = this.hasFileValidation(fileContent.content); const hasSizeLimits = this.hasSizeLimits(fileContent.content); const hasTypeChecking = this.hasTypeChecking(fileContent.content); return { isInComment: false, // Will be checked per line! isInString: false, // Will be checked per line! isInTestFile: this.isInTestFile(fileContent.path), isInDocumentation: this.isInDocumentation(fileContent.path), isInDevelopment: this.isInDevelopment(fileContent.path), language, framework, hasFileValidation, hasSizeLimits, hasTypeChecking, issueType: '' }; } isSafeContext(lineContent, filePath, context) { // Checks for validation patterns if (this.hasValidationPatterns(lineContent)) { return true; } if (this.isInComment(lineContent, filePath)) { return true; } if (context.isInTestFile || context.isInDocumentation) { return true; } if (this.isFalsePositive(lineContent)) { return true; } return false; } calculateConfidence(baseConfidence, context) { let confidence = baseConfidence; // Reduces confidence for development contexts if (context.isInDevelopment) { confidence *= 0.7; } // Increases confidence if file validation/size limits/type checking is present if (context.hasFileValidation) { confidence *= 0.8; } if (context.hasSizeLimits) { confidence *= 0.8; } if (context.hasTypeChecking) { confidence *= 0.8; } return Math.min(confidence, 1.0); } calculateSeverity(baseSeverity, confidence, context) { let severity = baseSeverity; // Never downgrades critical issues below high if (baseSeverity === 'critical' && confidence < 0.8) { return 'high'; } // Downgrades severity for development contexts if (context.isInDevelopment) { if (severity === 'critical') return 'high'; if (severity === 'high') return 'medium'; if (severity === 'medium') return 'low'; } return severity; } detectLanguage(filePath) { const ext = filePath.split('.').pop()?.toLowerCase(); switch (ext) { case 'js': return 'javascript'; case 'ts': return 'typescript'; case 'py': return 'python'; case 'php': return 'php'; case 'java': return 'java'; case 'cs': return 'csharp'; case 'rb': return 'ruby'; case 'go': return 'go'; case 'rs': return 'rust'; default: return 'unknown'; } } detectFramework(content, language) { const lowerContent = content.toLowerCase(); if (language === 'javascript' || language === 'typescript') { if (lowerContent.includes('express')) return 'express'; if (lowerContent.includes('react')) return 'react'; if (lowerContent.includes('vue')) return 'vue'; if (lowerContent.includes('angular')) return 'angular'; } if (language === 'python') { if (lowerContent.includes('django')) return 'django'; if (lowerContent.includes('flask')) return 'flask'; if (lowerContent.includes('fastapi')) return 'fastapi'; } if (language === 'php') { if (lowerContent.includes('laravel')) return 'laravel'; if (lowerContent.includes('symfony')) return 'symfony'; } if (language === 'java') { if (lowerContent.includes('spring')) return 'spring'; } if (language === 'ruby') { if (lowerContent.includes('rails')) return 'rails'; } return 'unknown'; } hasFileValidation(content) { const validationKeywords = ['fileFilter', 'validate', 'check', 'verify', 'sanitize', 'clean', 'whitelist', 'blacklist', 'allowed', 'permitted', 'safe', 'secure', 'type', 'mimetype', 'extension', 'filename', 'size', 'limit', 'max', 'restrict', 'filter', 'scan', 'virus', 'malware', 'antivirus']; return validationKeywords.some(keyword => content.toLowerCase().includes(keyword)); } hasSizeLimits(content) { const sizeKeywords = ['size', 'limit', 'max', 'bytes', 'mb', 'kb', 'gb']; return sizeKeywords.some(keyword => content.toLowerCase().includes(keyword)); } hasTypeChecking(content) { const typeKeywords = ['type', 'mimetype', 'extension', 'filename', 'content-type']; return typeKeywords.some(keyword => content.toLowerCase().includes(keyword)); } isInComment(lineContent, filePath) { const trimmedLine = lineContent.trim(); // Checks for single-line comments if (trimmedLine.startsWith('//') || trimmedLine.startsWith('#') || trimmedLine.startsWith('--') || trimmedLine.startsWith('*')) { return true; } // Language specific comment detection: Based on file extension! const ext = filePath.split('.').pop()?.toLowerCase(); switch (ext) { case 'py': // Python: # comments and """ docstrings """ if (trimmedLine.startsWith('#') || lineContent.includes('"""')) { return true; } break; case 'rb': // Ruby: # comments and =begin/=end blocks if (trimmedLine.startsWith('#') || lineContent.includes('=begin') || lineContent.includes('=end')) { return true; } break; case 'php': // PHP: //, #, and /* */ comments if (trimmedLine.startsWith('//') || trimmedLine.startsWith('#') || lineContent.includes('/*')) { return true; } break; case 'java': case 'cs': // Java/C#: // and /* */ comments if (trimmedLine.startsWith('//') || lineContent.includes('/*')) { return true; } break; case 'go': // Go: // and /* */ comments if (trimmedLine.startsWith('//') || lineContent.includes('/*')) { return true; } break; case 'rs': // Rust: // and /* */ comments if (trimmedLine.startsWith('//') || lineContent.includes('/*')) { return true; } break; case 'html': case 'xml': // HTML/XML: <!-- --> comments if (lineContent.includes('<!--')) { return true; } break; case 'css': // CSS: /* */ comments if (lineContent.includes('/*')) { return true; } break; case 'sql': // SQL: -- and /* */ comments if (trimmedLine.startsWith('--') || lineContent.includes('/*')) { return true; } break; case 'yaml': case 'yml': // YAML: # comments if (trimmedLine.startsWith('#')) { return true; } break; case 'ini': case 'properties': // INI/Properties: # and ; comments if (trimmedLine.startsWith('#') || trimmedLine.startsWith(';')) { return true; } break; } return false; } isInTestFile(filePath) { const testPatterns = [ /test/i, /spec/i, /mock/i, /stub/i, /fixture/i, /example/i, /sample/i, /demo/i ]; return testPatterns.some(pattern => pattern.test(filePath)); } isInDocumentation(filePath) { const docPatterns = [ /readme/i, /docs?/i, /documentation/i, /guide/i, /tutorial/i, /example/i, /sample/i ]; return docPatterns.some(pattern => pattern.test(filePath)); } isInDevelopment(filePath) { const devPatterns = [ /development/i, /dev/i, /staging/i, /localhost/i, /127\.0\.0\.1/i, /test/i, /debug/i ]; return devPatterns.some(pattern => pattern.test(filePath)); } isFalsePositive(lineContent) { const falsePositivePatterns = [ /example/i, /demo/i, /test/i, /mock/i, /sample/i, /placeholder/i, /your[_-]?file/i, /dummy/i, /fake/i, /development/i, /dev/i, /staging/i ]; return falsePositivePatterns.some(pattern => pattern.test(lineContent)); } // Validation methods: For file upload patterns! validateDirectFileMove(text) { return text.toLowerCase().includes('file.mv') && text.includes('./uploads/') && text.includes('file.name'); } validatePHPFileMove(text) { return text.toLowerCase().includes('move_uploaded_file') && (text.includes('$_FILES') || text.includes('$_GET') || text.includes('$_POST')); } validateAnyFileUpload(text) { return text.toLowerCase().includes('.any('); } validateMulterUpload(text) { return text.toLowerCase().includes('multer(') && text.includes('{') && text.includes('}'); } validateSingleFileUpload(text) { return text.toLowerCase().includes('.single('); } validateArrayFileUpload(text) { return text.toLowerCase().includes('.array('); } validateFieldsUpload(text) { return text.toLowerCase().includes('.fields(') && text.includes('[') && text.includes(']'); } validateFileSystemOperation(text) { return (text.toLowerCase().includes('fs.') || text.includes("require('fs')")) && (text.includes('readFile') || text.includes('writeFile') || text.includes('createReadStream') || text.includes('createWriteStream')); } validatePHPFileCopy(text) { return text.toLowerCase().includes('copy(') && (text.includes('$_FILES') || text.includes('$_GET') || text.includes('$_POST')); } validatePHPFileUpload(text) { return text.toLowerCase().includes('$_FILES['); } validatePythonFileUpload(text) { return text.toLowerCase().includes('request.files['); } validateJavaFileUpload(text) { return text.toLowerCase().includes('request.getPart('); } validateJavaFilePart(text) { return text.toLowerCase().includes('part') && text.includes('filepart') && text.includes('request.getpart'); } validatePythonFileOpen(text) { return text.toLowerCase().includes('open(') && (text.includes('request.files') || text.includes('flask.request.files')); } validateFileMove(text) { return text.toLowerCase().includes('file.mv('); } validateFileOperation(text) { return (text.includes('readFile') || text.includes('writeFile') || text.includes('createReadStream') || text.includes('createWriteStream')) && (text.includes('req.') || text.includes('request.') || text.includes('input.') || text.includes('params.') || text.includes('query.') || text.includes('body.')); } validateFileExtensionAssignment(text) { return !!(text.match(/\.(?:jpg|jpeg|png|gif|pdf|doc|docx|txt)\s*[:=]/i)) && (text.includes('req.') || text.includes('request.') || text.includes('input.') || text.includes('params.') || text.includes('query.') || text.includes('body.')); } validateFilenameAssignment(text) { return (text.toLowerCase().includes('filename') || text.includes('originalname')) && text.includes('=') && (text.includes('req.') || text.includes('request.') || text.includes('input.') || text.includes('params.') || text.includes('query.') || text.includes('body.')); } validateFileSizeAssignment(text) { return (text.toLowerCase().includes('size') || text.includes('length')) && text.includes('=') && (text.includes('req.') || text.includes('request.') || text.includes('input.') || text.includes('params.') || text.includes('query.') || text.includes('body.')); } validateFileSizeCheck(text) { return (text.toLowerCase().includes('bytes') || text.includes('size')) && text.includes('>') && /\d+/.test(text); } generateSuggestion(issueType, context) { const framework = context.framework; switch (issueType) { case 'Direct file move with original filename': if (framework === 'express') { return 'Use multer with fileFilter, validate file types, generate unique filenames, and implement proper file size limits. Consider using express-fileupload with validation.'; } return 'Generate unique filenames, validate file types, implement size limits, and use secure file upload libraries with built-in validation.'; case 'PHP file move without validation': if (framework === 'laravel') { return 'Use Laravel\'s built-in file validation with Request validation rules. Implement file type checking, size limits, and use Storage facade for secure file handling.'; } return 'Validate file types, check file size, generate unique filenames, and use proper file upload validation before moving files.'; case 'Any file upload without validation': return 'Never use .any() in production. Implement strict file type validation, size limits, and use whitelist approach for allowed file types.'; case 'Multer upload without validation': return 'Configure multer with fileFilter function, set size limits, validate file types, and implement proper error handling. Use whitelist approach for allowed extensions.'; case 'Single file upload without validation': return 'Add fileFilter function to multer configuration, validate file types and size, implement proper error handling, and use whitelist approach.'; case 'Multiple file upload without validation': return 'Configure multer with fileFilter for multiple files, set size limits, validate file types, and implement proper error handling for each file.'; case 'Multiple fields upload without validation': return 'Add validation for each field in multer fields configuration, implement file type checking, size limits, and proper error handling.'; case 'File system operation without validation': return 'Validate file paths, check file types, implement size limits, and sanitize user input before performing file system operations.'; case 'PHP file copy without validation': return 'Validate file types, check file size, sanitize filenames, and implement proper file upload validation before copying files.'; case 'PHP file upload without validation': if (framework === 'laravel') { return 'Use Laravel\'s Request validation with file rules. Implement file type checking, size limits, and use Storage facade for secure handling.'; } return 'Validate file types, check file size, sanitize filenames, and implement proper file upload validation.'; case 'Python file upload without validation': if (framework === 'django') { return 'Use Django forms with FileField validation. Implement file type checking, size limits, and use Django\'s built-in file handling.'; } else if (framework === 'flask') { return 'Use Flask-WTF for file upload validation. Implement file type checking, size limits, and secure file handling.'; } return 'Validate file types, check file size, sanitize filenames, and implement proper file upload validation.'; case 'Java file upload without validation': if (framework === 'spring') { return 'Use Spring MultipartFile with validation annotations. Implement file type checking, size limits, and use Spring\'s built-in file handling.'; } return 'Validate file types, check file size, sanitize filenames, and implement proper file upload validation.'; case 'Java file part without validation': if (framework === 'spring') { return 'Use Spring MultipartFile with @Valid annotation and validation rules. Implement file type checking and size limits.'; } return 'Validate file types, check file size, sanitize filenames, and implement proper file upload validation.'; case 'Python file open without validation': if (framework === 'django') { return 'Use Django\'s FileField and forms validation. Implement file type checking and size limits before opening files.'; } else if (framework === 'flask') { return 'Use Flask-WTF for file validation. Implement file type checking and size limits before opening files.'; } return 'Validate file types and size before opening files. Implement proper file upload validation.'; case 'File move without validation': return 'Validate file types, check file size, generate unique filenames, and implement proper file upload validation before moving files.'; case 'File operation without type validation': return 'Validate file types, check file size, sanitize file paths, and implement proper file upload validation before performing file operations.'; case 'File extension assignment without validation': return 'Validate file extensions, use whitelist approach, check file types, and implement proper file upload validation.'; case 'Filename assignment without validation': return 'Generate unique filenames, validate file types, sanitize filenames, and implement proper file upload validation.'; case 'File size without limits': return 'Implement file size limits, validate file types, and implement proper file upload validation with size restrictions.'; case 'File size check without proper validation': return 'Implement comprehensive file validation including type checking, size limits, and proper error handling.'; default: return 'Implement proper file upload validation including file type checking, size limits, and dangerous extension filtering. Use whitelist approach for allowed file types.'; } } generateDangerousExtensionSuggestion(extensionPattern, context) { const framework = context.framework; if (extensionPattern.includes('php|asp|jsp|exe|bat|cmd|com|scr|pif|vbs|js|jar|war|ear|sh|pl|py|rb|cgi')) { if (framework === 'express') { return 'Block executable file extensions. Use multer fileFilter to whitelist only safe file types. Implement strict file type validation.'; } else if (framework === 'django') { return 'Block executable file extensions. Use Django forms with FileField validation and custom validators to whitelist safe file types.'; } else if (framework === 'rails') { return 'Block executable file extensions. Use Rails file validation with whitelist approach for allowed file types.'; } else if (framework === 'spring') { return 'Block executable file extensions. Use Spring MultipartFile validation with custom validators to whitelist safe file types.'; } return 'Block dangerous executable file extensions. Implement strict file type validation and use whitelist approach for allowed file types.'; } else if (extensionPattern.includes('svg|zip|rar|7z|tar|gz|bz2|xz')) { return 'Carefully validate SVG files for XSS and archive files for zip bombs. Implement file content validation and size limits.'; } else { return 'Implement strict file type validation and use whitelist approach for allowed file types. Block potentially dangerous file extensions.'; } } } exports.InsecureFileUploadRule = InsecureFileUploadRule; //# sourceMappingURL=insecure-file-upload.js.map