smartui-migration-tool
Version:
Enterprise-grade CLI tool for migrating visual testing platforms to LambdaTest SmartUI
831 lines (718 loc) ⢠28.5 kB
JavaScript
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;