UNPKG

smartui-migration-tool

Version:

Enterprise-grade CLI tool for migrating visual testing platforms to LambdaTest SmartUI

831 lines (718 loc) • 28.5 kB
const { Command, Flags } = require('@oclif/core'); const chalk = require('chalk'); const fs = require('fs-extra'); const path = require('path'); const glob = require('glob'); class ComplianceChecker extends Command { static description = 'Comprehensive compliance checker for OWASP, PCI-DSS, SOX, GDPR, HIPAA, and other standards'; static flags = { path: Flags.string({ char: 'p', description: 'Path to check (default: current directory)', default: process.cwd() }), include: Flags.string({ char: 'i', description: 'File patterns to include (comma-separated)', default: '**/*.{js,ts,jsx,tsx,py,java,cs,json,yaml,yml,md}' }), exclude: Flags.string({ char: 'e', description: 'File patterns to exclude (comma-separated)', default: 'node_modules/**,dist/**,build/**,*.min.js' }), standard: Flags.string({ char: 's', description: 'Compliance standard to check against', options: ['owasp', 'pci-dss', 'sox', 'gdpr', 'hipaa', 'iso27001', 'nist', 'all'], default: 'all' }), level: Flags.string({ char: 'l', description: 'Compliance level to check', options: ['basic', 'intermediate', 'advanced', 'enterprise'], default: 'intermediate' }), output: Flags.string({ char: 'o', description: 'Output file for compliance report', default: 'compliance-report.json' }), format: Flags.string({ char: 'f', description: 'Output format for report', options: ['json', 'html', 'pdf', 'excel', 'sarif'], default: 'json' }), generate: Flags.boolean({ char: 'g', description: 'Generate compliance documentation', default: false }), fix: Flags.boolean({ char: 'F', description: 'Generate fix suggestions', default: true }), verbose: Flags.boolean({ char: 'v', description: 'Enable verbose output', default: false }) }; async run() { const { flags } = await this.parse(ComplianceChecker); console.log(chalk.blue.bold('\nšŸ“‹ Compliance Checker')); console.log(chalk.gray(`Checking ${flags.standard} compliance at ${flags.level} level...\n`)); try { // Create compliance checker const checker = this.createComplianceChecker(flags.standard, flags.level); // Find files to check const files = await this.findFiles(flags); // Perform compliance check const results = await this.performComplianceCheck(files, flags, checker); // Display results this.displayResults(results, flags.verbose); // Save results await this.saveResults(results, flags.output, flags.format); console.log(chalk.green(`\nāœ… Compliance report saved to: ${flags.output}`)); // Generate documentation if requested if (flags.generate) { await this.generateDocumentation(results, flags); } } catch (error) { console.error(chalk.red(`\nāŒ Error during compliance check: ${error.message}`)); this.exit(1); } } createComplianceChecker(standard, level) { return { // OWASP Compliance checkOWASP: async (files) => { const issues = []; for (const file of files) { try { const content = await fs.readFile(file.path, 'utf8'); const owaspIssues = this.checkOWASPTop10(content, file.path, level); issues.push(...owaspIssues); } catch (error) { // Skip files that can't be read } } return issues; }, // PCI-DSS Compliance checkPCIDSS: async (files) => { const issues = []; for (const file of files) { try { const content = await fs.readFile(file.path, 'utf8'); const pciIssues = this.checkPCIDSSRequirements(content, file.path, level); issues.push(...pciIssues); } catch (error) { // Skip files that can't be read } } return issues; }, // SOX Compliance checkSOX: async (files) => { const issues = []; for (const file of files) { try { const content = await fs.readFile(file.path, 'utf8'); const soxIssues = this.checkSOXRequirements(content, file.path, level); issues.push(...soxIssues); } catch (error) { // Skip files that can't be read } } return issues; }, // GDPR Compliance checkGDPR: async (files) => { const issues = []; for (const file of files) { try { const content = await fs.readFile(file.path, 'utf8'); const gdprIssues = this.checkGDPRRequirements(content, file.path, level); issues.push(...gdprIssues); } catch (error) { // Skip files that can't be read } } return issues; }, // HIPAA Compliance checkHIPAA: async (files) => { const issues = []; for (const file of files) { try { const content = await fs.readFile(file.path, 'utf8'); const hipaaIssues = this.checkHIPAARequirements(content, file.path, level); issues.push(...hipaaIssues); } catch (error) { // Skip files that can't be read } } return issues; }, // ISO 27001 Compliance checkISO27001: async (files) => { const issues = []; for (const file of files) { try { const content = await fs.readFile(file.path, 'utf8'); const isoIssues = this.checkISO27001Requirements(content, file.path, level); issues.push(...isoIssues); } catch (error) { // Skip files that can't be read } } return issues; }, // NIST Compliance checkNIST: async (files) => { const issues = []; for (const file of files) { try { const content = await fs.readFile(file.path, 'utf8'); const nistIssues = this.checkNISTRequirements(content, file.path, level); issues.push(...nistIssues); } catch (error) { // Skip files that can't be read } } return issues; } }; } async performComplianceCheck(files, flags, checker) { const results = { timestamp: new Date().toISOString(), standard: flags.standard, level: flags.level, data: {}, summary: {} }; // Perform checks based on standard if (flags.standard === 'all' || flags.standard === 'owasp') { results.data.owasp = await checker.checkOWASP(files); } if (flags.standard === 'all' || flags.standard === 'pci-dss') { results.data.pci_dss = await checker.checkPCIDSS(files); } if (flags.standard === 'all' || flags.standard === 'sox') { results.data.sox = await checker.checkSOX(files); } if (flags.standard === 'all' || flags.standard === 'gdpr') { results.data.gdpr = await checker.checkGDPR(files); } if (flags.standard === 'all' || flags.standard === 'hipaa') { results.data.hipaa = await checker.checkHIPAA(files); } if (flags.standard === 'all' || flags.standard === 'iso27001') { results.data.iso27001 = await checker.checkISO27001(files); } if (flags.standard === 'all' || flags.standard === 'nist') { results.data.nist = await checker.checkNIST(files); } // Generate summary results.summary = this.generateSummary(results.data, flags.level); return results; } async findFiles(flags) { const includePatterns = flags.include.split(','); const excludePatterns = flags.exclude.split(','); const files = []; for (const pattern of includePatterns) { const matches = glob.sync(pattern, { cwd: flags.path, absolute: true, ignore: excludePatterns }); files.push(...matches.map(file => ({ path: file }))); } return files; } checkOWASPTop10(content, filePath, level) { const issues = []; // A01:2021 - Broken Access Control if (level !== 'basic') { if (content.includes('admin') && !content.includes('authorize') && !content.includes('permission')) { issues.push({ standard: 'OWASP', category: 'A01:2021 - Broken Access Control', severity: 'high', file: filePath, line: this.findLineNumber(content, 'admin'), description: 'Potential broken access control detected', requirement: 'Implement proper authorization checks for admin functions', recommendation: 'Add role-based access control (RBAC) and authorization checks', cwe: 'CWE-285', level: level }); } } // A02:2021 - Cryptographic Failures if (content.includes('md5') || content.includes('sha1')) { issues.push({ standard: 'OWASP', category: 'A02:2021 - Cryptographic Failures', severity: 'medium', file: filePath, line: this.findLineNumber(content, 'md5') || this.findLineNumber(content, 'sha1'), description: 'Weak cryptographic algorithm detected', requirement: 'Use strong cryptographic algorithms', recommendation: 'Replace MD5/SHA1 with SHA-256 or stronger', cwe: 'CWE-327', level: level }); } // A03:2021 - Injection if (content.includes('query(') && !content.includes('parameterized') && !content.includes('prepared')) { issues.push({ standard: 'OWASP', category: 'A03:2021 - Injection', severity: 'high', file: filePath, line: this.findLineNumber(content, 'query('), description: 'Potential SQL injection vulnerability', requirement: 'Use parameterized queries', recommendation: 'Implement parameterized queries or prepared statements', cwe: 'CWE-89', level: level }); } // A04:2021 - Insecure Design if (level === 'advanced' || level === 'enterprise') { if (content.includes('password') && content.includes('=') && !content.includes('hash')) { issues.push({ standard: 'OWASP', category: 'A04:2021 - Insecure Design', severity: 'high', file: filePath, line: this.findLineNumber(content, 'password'), description: 'Insecure password handling detected', requirement: 'Implement secure password handling', recommendation: 'Use password hashing and secure storage', cwe: 'CWE-256', level: level }); } } // A05:2021 - Security Misconfiguration if (content.includes('debug') && content.includes('true')) { issues.push({ standard: 'OWASP', category: 'A05:2021 - Security Misconfiguration', severity: 'medium', file: filePath, line: this.findLineNumber(content, 'debug'), description: 'Debug mode enabled in production code', requirement: 'Disable debug mode in production', recommendation: 'Set debug to false in production environment', cwe: 'CWE-489', level: level }); } return issues; } checkPCIDSSRequirements(content, filePath, level) { const issues = []; // Requirement 3: Protect stored cardholder data if (content.includes('card') && content.includes('number')) { issues.push({ standard: 'PCI-DSS', category: 'Requirement 3 - Protect stored cardholder data', severity: 'critical', file: filePath, line: this.findLineNumber(content, 'card'), description: 'Cardholder data storage detected', requirement: 'Encrypt stored cardholder data', recommendation: 'Implement tokenization and encryption for cardholder data', pci_requirement: '3.4', level: level }); } // Requirement 6: Develop and maintain secure systems if (content.includes('eval(') || content.includes('innerHTML')) { issues.push({ standard: 'PCI-DSS', category: 'Requirement 6 - Develop and maintain secure systems', severity: 'high', file: filePath, line: this.findLineNumber(content, 'eval(') || this.findLineNumber(content, 'innerHTML'), description: 'Insecure coding practices detected', requirement: 'Use secure coding practices', recommendation: 'Avoid eval() and sanitize innerHTML usage', pci_requirement: '6.5', level: level }); } return issues; } checkSOXRequirements(content, filePath, level) { const issues = []; // SOX Section 404 - Internal Controls if (level === 'advanced' || level === 'enterprise') { if (content.includes('financial') && !content.includes('audit')) { issues.push({ standard: 'SOX', category: 'Section 404 - Internal Controls', severity: 'medium', file: filePath, line: this.findLineNumber(content, 'financial'), description: 'Financial data processing without audit trail', requirement: 'Implement audit trails for financial data', recommendation: 'Add comprehensive logging and audit trails', sox_section: '404', level: level }); } } return issues; } checkGDPRRequirements(content, filePath, level) { const issues = []; // GDPR Article 32 - Security of processing if (content.includes('personal') && content.includes('data') && !content.includes('encrypt')) { issues.push({ standard: 'GDPR', category: 'Article 32 - Security of processing', severity: 'high', file: filePath, line: this.findLineNumber(content, 'personal'), description: 'Personal data processing without encryption', requirement: 'Implement appropriate technical measures', recommendation: 'Encrypt personal data and implement data protection measures', gdpr_article: '32', level: level }); } // GDPR Article 25 - Data protection by design if (level === 'advanced' || level === 'enterprise') { if (content.includes('consent') && !content.includes('explicit')) { issues.push({ standard: 'GDPR', category: 'Article 25 - Data protection by design', severity: 'medium', file: filePath, line: this.findLineNumber(content, 'consent'), description: 'Consent handling may not meet GDPR requirements', requirement: 'Implement data protection by design', recommendation: 'Ensure explicit consent mechanisms and privacy by design', gdpr_article: '25', level: level }); } } return issues; } checkHIPAARequirements(content, filePath, level) { const issues = []; // HIPAA Security Rule - Administrative Safeguards if (content.includes('patient') && content.includes('data')) { issues.push({ standard: 'HIPAA', category: 'Security Rule - Administrative Safeguards', severity: 'high', file: filePath, line: this.findLineNumber(content, 'patient'), description: 'Patient data handling detected', requirement: 'Implement administrative safeguards', recommendation: 'Ensure proper access controls and data handling procedures', hipaa_rule: '164.308', level: level }); } // HIPAA Security Rule - Technical Safeguards if (content.includes('health') && !content.includes('encrypt')) { issues.push({ standard: 'HIPAA', category: 'Security Rule - Technical Safeguards', severity: 'critical', file: filePath, line: this.findLineNumber(content, 'health'), description: 'Health information without encryption', requirement: 'Implement technical safeguards', recommendation: 'Encrypt all health information and implement access controls', hipaa_rule: '164.312', level: level }); } return issues; } checkISO27001Requirements(content, filePath, level) { const issues = []; // ISO 27001 - Information Security Management if (level === 'advanced' || level === 'enterprise') { if (content.includes('confidential') && !content.includes('classify')) { issues.push({ standard: 'ISO 27001', category: 'Information Security Management', severity: 'medium', file: filePath, line: this.findLineNumber(content, 'confidential'), description: 'Confidential information without classification', requirement: 'Implement information classification', recommendation: 'Classify information and implement appropriate controls', iso_control: 'A.8.2.1', level: level }); } } return issues; } checkNISTRequirements(content, filePath, level) { const issues = []; // NIST Cybersecurity Framework if (content.includes('network') && content.includes('http://')) { issues.push({ standard: 'NIST', category: 'Protect - Data Security', severity: 'medium', file: filePath, line: this.findLineNumber(content, 'http://'), description: 'Insecure network communication detected', requirement: 'Protect data in transit', recommendation: 'Use HTTPS for all network communications', nist_function: 'PR.DS-2', level: level }); } return issues; } findLineNumber(content, searchString) { const lines = content.split('\n'); for (let i = 0; i < lines.length; i++) { if (lines[i].includes(searchString)) { return i + 1; } } return 1; } generateSummary(data, level) { const summary = { level, standards: {}, totalIssues: 0, bySeverity: { critical: 0, high: 0, medium: 0, low: 0 }, complianceScore: 0, generated: new Date().toISOString() }; // Count issues by standard for (const [standard, issues] of Object.entries(data)) { summary.standards[standard] = { total: issues.length, bySeverity: { critical: 0, high: 0, medium: 0, low: 0 } }; issues.forEach(issue => { summary.totalIssues++; summary.bySeverity[issue.severity]++; summary.standards[standard].bySeverity[issue.severity]++; }); } // Calculate compliance score summary.complianceScore = this.calculateComplianceScore(summary.bySeverity, level); return summary; } calculateComplianceScore(severityCounts, level) { const weights = { critical: 10, high: 7, medium: 4, low: 1 }; const levelMultipliers = { basic: 1, intermediate: 1.2, advanced: 1.5, enterprise: 2 }; let score = 100; const multiplier = levelMultipliers[level] || 1; for (const [severity, count] of Object.entries(severityCounts)) { score -= count * (weights[severity] || 0) * multiplier; } return Math.max(score, 0); } async saveResults(results, outputFile, format) { if (format === 'json') { await fs.writeJson(outputFile, results, { spaces: 2 }); } else if (format === 'html') { const html = this.generateHTMLReport(results); await fs.writeFile(outputFile.replace('.json', '.html'), html); } else if (format === 'pdf') { // Mock PDF generation console.log(chalk.blue('šŸ“„ PDF report generation would be implemented here')); } else if (format === 'excel') { // Mock Excel generation console.log(chalk.blue('šŸ“Š Excel report generation would be implemented here')); } } generateHTMLReport(results) { return ` <!DOCTYPE html> <html> <head> <title>Compliance Report</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .header { background: #f0f0f0; padding: 20px; border-radius: 5px; } .summary { margin: 20px 0; } .issue { border: 1px solid #ddd; margin: 10px 0; padding: 15px; border-radius: 5px; } .critical { border-left: 5px solid #dc3545; } .high { border-left: 5px solid #fd7e14; } .medium { border-left: 5px solid #ffc107; } .low { border-left: 5px solid #28a745; } .compliance-score { font-size: 24px; font-weight: bold; } </style> </head> <body> <div class="header"> <h1>Compliance Report</h1> <p>Generated: ${results.timestamp}</p> <p>Standard: ${results.standard}</p> <p>Level: ${results.level}</p> <p class="compliance-score">Compliance Score: ${results.summary.complianceScore}/100</p> </div> <div class="summary"> <h2>Summary</h2> <p>Total Issues: ${results.summary.totalIssues}</p> <p>Critical: ${results.summary.bySeverity.critical}</p> <p>High: ${results.summary.bySeverity.high}</p> <p>Medium: ${results.summary.bySeverity.medium}</p> <p>Low: ${results.summary.bySeverity.low}</p> </div> ${Object.entries(results.data).map(([standard, issues]) => ` <div class="standard"> <h2>${standard.toUpperCase()}</h2> ${issues.map(issue => ` <div class="issue ${issue.severity}"> <h3>${issue.category} - ${issue.severity.toUpperCase()}</h3> <p><strong>File:</strong> ${issue.file}</p> <p><strong>Description:</strong> ${issue.description}</p> <p><strong>Requirement:</strong> ${issue.requirement}</p> <p><strong>Recommendation:</strong> ${issue.recommendation}</p> </div> `).join('')} </div> `).join('')} </body> </html>`; } async generateDocumentation(results, flags) { console.log(chalk.blue('\nšŸ“š Generating compliance documentation...')); const docDir = 'compliance-docs'; await fs.ensureDir(docDir); // Generate compliance policies const policies = this.generateCompliancePolicies(results.summary.standards); await fs.writeJson(path.join(docDir, 'compliance-policies.json'), policies, { spaces: 2 }); // Generate remediation guide const remediation = this.generateRemediationGuide(results.data); await fs.writeJson(path.join(docDir, 'remediation-guide.json'), remediation, { spaces: 2 }); console.log(chalk.green(`āœ… Compliance documentation generated in: ${docDir}`)); } generateCompliancePolicies(standards) { const policies = {}; for (const [standard, data] of Object.entries(standards)) { policies[standard] = { name: standard.toUpperCase(), description: `Compliance policy for ${standard.toUpperCase()}`, requirements: this.getStandardRequirements(standard), controls: this.getStandardControls(standard), monitoring: this.getMonitoringRequirements(standard) }; } return policies; } generateRemediationGuide(issues) { const guide = { title: 'Compliance Remediation Guide', sections: {} }; for (const [standard, standardIssues] of Object.entries(issues)) { guide.sections[standard] = { name: standard.toUpperCase(), issues: standardIssues.map(issue => ({ category: issue.category, severity: issue.severity, description: issue.description, recommendation: issue.recommendation, priority: this.getPriority(issue.severity) })) }; } return guide; } getStandardRequirements(standard) { const requirements = { 'owasp': ['A01:2021 - Broken Access Control', 'A02:2021 - Cryptographic Failures', 'A03:2021 - Injection'], 'pci_dss': ['Requirement 3 - Protect stored cardholder data', 'Requirement 6 - Develop and maintain secure systems'], 'gdpr': ['Article 32 - Security of processing', 'Article 25 - Data protection by design'], 'hipaa': ['Security Rule - Administrative Safeguards', 'Security Rule - Technical Safeguards'] }; return requirements[standard] || []; } getStandardControls(standard) { const controls = { 'owasp': ['Access Control', 'Encryption', 'Input Validation', 'Secure Configuration'], 'pci_dss': ['Data Encryption', 'Secure Coding', 'Access Control', 'Network Security'], 'gdpr': ['Data Encryption', 'Consent Management', 'Data Minimization', 'Right to Erasure'], 'hipaa': ['Access Control', 'Audit Logs', 'Data Encryption', 'Risk Assessment'] }; return controls[standard] || []; } getMonitoringRequirements(standard) { const monitoring = { 'owasp': ['Vulnerability Scanning', 'Penetration Testing', 'Code Review', 'Security Training'], 'pci_dss': ['Quarterly Vulnerability Scans', 'Annual Penetration Testing', 'Continuous Monitoring'], 'gdpr': ['Data Protection Impact Assessment', 'Privacy by Design Review', 'Consent Management Monitoring'], 'hipaa': ['Risk Assessment', 'Security Incident Monitoring', 'Access Review', 'Audit Log Review'] }; return monitoring[standard] || []; } getPriority(severity) { const priorities = { critical: 1, high: 2, medium: 3, low: 4 }; return priorities[severity] || 5; } displayResults(results, verbose) { console.log(chalk.green.bold('\nšŸ“‹ Compliance Check Results')); console.log(chalk.gray('=' * 50)); // Summary console.log(chalk.blue.bold('\nšŸ“Š Summary:')); console.log(` Compliance Score: ${chalk.blue(results.summary.complianceScore)}/100`); console.log(` Total Issues: ${results.summary.totalIssues}`); console.log(` Level: ${results.summary.level}`); // Severity breakdown console.log(chalk.blue.bold('\nāš ļø Severity Breakdown:')); for (const [severity, count] of Object.entries(results.summary.bySeverity)) { const color = severity === 'critical' ? chalk.red : severity === 'high' ? chalk.yellow : severity === 'medium' ? chalk.blue : chalk.green; console.log(` ${color(severity.toUpperCase())}: ${count}`); } // Standards breakdown console.log(chalk.blue.bold('\nšŸ“‹ Standards Breakdown:')); for (const [standard, data] of Object.entries(results.summary.standards)) { console.log(` ${standard.toUpperCase()}: ${data.total} issues`); } // Issues by standard for (const [standard, issues] of Object.entries(results.data)) { if (issues.length > 0) { console.log(chalk.blue.bold(`\nšŸ” ${standard.toUpperCase()} Issues:`)); issues.forEach((issue, index) => { const severity = issue.severity === 'critical' ? chalk.red('šŸ”“') : issue.severity === 'high' ? chalk.yellow('🟔') : issue.severity === 'medium' ? chalk.blue('šŸ”µ') : chalk.green('🟢'); console.log(` ${index + 1}. ${severity} ${issue.category} - ${issue.severity.toUpperCase()}`); console.log(` File: ${issue.file}:${issue.line}`); console.log(` Description: ${issue.description}`); console.log(` Requirement: ${issue.requirement}`); console.log(` Recommendation: ${issue.recommendation}`); if (issue.cwe) console.log(` CWE: ${issue.cwe}`); if (issue.owasp) console.log(` OWASP: ${issue.owasp}`); if (issue.pci_requirement) console.log(` PCI Requirement: ${issue.pci_requirement}`); if (issue.gdpr_article) console.log(` GDPR Article: ${issue.gdpr_article}`); if (issue.hipaa_rule) console.log(` HIPAA Rule: ${issue.hipaa_rule}`); }); } } if (verbose) { console.log(chalk.blue.bold('\nšŸ” Detailed Results:')); console.log(JSON.stringify(results, null, 2)); } } } module.exports.default = ComplianceChecker;