@iota-big3/sdk-security
Version:
Advanced security features including zero trust, quantum-safe crypto, and ML threat detection
314 lines • 10.9 kB
JavaScript
"use strict";
/**
* @iota-big3/sdk-security - Security Scanner
* SAST, DAST, SCA and other security scanning capabilities
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SecurityScanner = void 0;
const events_1 = require("events");
class SecurityScanner extends events_1.EventEmitter {
constructor(config, logger) {
super();
this.isEnabled = true;
this.scans = [];
this.schedules = new Map();
this.customScanners = new Map();
this.isInitialized = false;
this.config = config;
this.logger = logger;
this.enabledScanners = new Set(config.enabledScanners);
}
async initialize() {
if (this.isInitialized) {
return;
}
try {
this.logger.info('Initializing security scanner');
// Initialize scanning engines
await this.initializeScanners();
this.isInitialized = true;
this.emit('scanner:initialized');
}
catch (error) {
this.logger.error('Failed to initialize security scanner', error);
this.emit('scanner:error', error);
throw error;
}
}
async initializeScanners() {
// Initialize each scanner type
for (const scanner of this.enabledScanners) {
this.logger.debug(`Initializing ${scanner} scanner`);
}
}
async startScan(type, target, context) {
const scan = {
id: this.generateScanId(),
type,
target,
context,
status: 'running',
startTime: new Date(),
findings: [],
summary: {
totalFindings: 0,
criticalCount: 0,
highCount: 0,
mediumCount: 0,
lowCount: 0
}
};
this.scans.push(scan);
this.emit('scan:started', scan);
// Simulate async scanning
setTimeout(async () => {
try {
const findings = await this.performScan(type, target, context);
scan.findings = findings;
scan.status = 'completed';
scan.endTime = new Date();
scan.summary = this.calculateSummary(findings);
this.emit('scan:completed', scan);
}
catch (error) {
scan.status = 'failed';
scan.endTime = new Date();
this.emit('scan:failed', scan, error);
}
}, 50); // Simulate scan time
return scan.id;
}
async performScan(type, target, context) {
const findings = [];
// Use custom scanner if available
if (this.customScanners.has(type)) {
const scanner = this.customScanners.get(type);
const result = await scanner.scan(target, context);
return result.findings;
}
// Mock findings for demonstration
if (type === 'SAST') {
findings.push({
id: `finding-${Date.now()}-1`,
type: 'SQL_INJECTION',
severity: 'HIGH',
title: 'Potential SQL Injection',
description: 'User input not properly sanitized',
recommendation: 'Use parameterized queries',
cve: 'CWE-89'
});
}
else if (type === 'SCA') {
findings.push({
id: `finding-${Date.now()}-2`,
type: 'VULNERABLE_DEPENDENCY',
severity: 'CRITICAL',
title: 'Vulnerable dependency detected',
description: 'lodash@4.17.19 has known vulnerabilities',
recommendation: 'Update to lodash@4.17.21',
cve: 'CVE-2021-23337',
cvssScore: 7.2
});
}
return findings;
}
async runFullScan(target) {
const results = new Map();
for (const scanType of this.enabledScanners) {
const scanId = await this.startScan(scanType, target, 'full-scan');
// Wait for scan to complete
await new Promise(resolve => {
const checkInterval = setInterval(() => {
const scan = this.scans.find(s => s.id === scanId);
if (scan && scan.status !== 'running') {
clearInterval(checkInterval);
results.set(scanType, {
findings: scan.findings,
summary: scan.summary
});
resolve(undefined);
}
}, 10);
});
}
return results;
}
getFindings(options) {
const allFindings = this.scans.flatMap(scan => scan.findings);
if (options?.severityThreshold) {
const severityOrder = { 'critical': 4, 'high': 3, 'medium': 2, 'low': 1 };
const threshold = severityOrder[options.severityThreshold.toLowerCase()] || 0;
return allFindings.filter(finding => {
const findingSeverity = severityOrder[finding.severity.toLowerCase()] || 0;
return findingSeverity >= threshold;
});
}
return allFindings;
}
getScans() {
return this.scans;
}
getEnabledScanners() {
return Array.from(this.enabledScanners);
}
enableScanner(type) {
this.enabledScanners.add(type);
}
disableScanner(type) {
this.enabledScanners.delete(type);
}
addCustomScanner(type, scanner) {
this.customScanners.set(type, scanner);
this.emit('scanner:added', type);
}
exportResults(scan, format) {
switch (format) {
case 'sarif':
return this.exportSARIF(scan);
case 'json':
return this.exportJSON(scan);
case 'csv':
return this.exportCSV(scan);
default:
return this.exportJSON(scan);
}
}
exportSARIF(scan) {
const sarif = {
version: '2.1.0',
runs: [{
tool: {
driver: {
name: `IotaSDK ${scan.type} Scanner`,
version: '2.0.0'
}
},
results: scan.findings.map(finding => ({
ruleId: finding.type,
level: this.severityToSarifLevel(finding.severity),
message: {
text: finding.description
},
fixes: finding.recommendation ? [{
description: {
text: finding.recommendation
}
}] : undefined
}))
}]
};
return JSON.stringify(sarif, null, 2);
}
exportJSON(scan) {
return JSON.stringify({
scan: {
id: scan.id,
type: scan.type,
target: scan.target,
startTime: scan.startTime,
endTime: scan.endTime,
status: scan.status
},
findings: scan.findings,
summary: scan.summary
}, null, 2);
}
exportCSV(scan) {
const headers = 'severity,type,file,line,message,recommendation,cve\n';
const rows = scan.findings.map(finding => `${finding.severity},${finding.type},"${scan.target}",0,"${finding.description}","${finding.recommendation || ''}","${finding.cve || ''}"`).join('\n');
return headers + rows;
}
scheduleScan(schedule) {
const scheduleId = this.generateScheduleId();
const scanSchedule = {
id: scheduleId,
type: schedule.type,
target: schedule.target,
schedule: schedule.schedule
};
this.schedules.set(scheduleId, scanSchedule);
this.emit('scan:scheduled', scanSchedule);
return scheduleId;
}
cancelScheduledScan(scheduleId) {
if (this.schedules.delete(scheduleId)) {
this.emit('scan:cancelled', scheduleId);
}
}
getStats() {
const activeScans = this.scans.filter(s => s.status === 'running').length;
const totalFindings = this.scans.reduce((sum, scan) => sum + scan.findings.length, 0);
return {
isInitialized: this.isInitialized,
totalScans: this.scans.length,
activeScans,
enabledScanners: Array.from(this.enabledScanners),
findingsCount: totalFindings,
schedules: this.schedules.size,
config: {
severityThreshold: this.config.severityThreshold,
scheduledScans: this.config.scheduledScans,
scanOnCommit: this.config.scanOnCommit
}
};
}
async shutdown() {
if (!this.isInitialized) {
return;
}
try {
this.schedules.clear();
this.scans = [];
this.customScanners.clear();
this.isInitialized = false;
this.emit('scanner:shutdown');
}
catch (error) {
this.logger.error('Error during scanner shutdown', error);
throw error;
}
}
generateScanId() {
return `scan-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
generateScheduleId() {
return `schedule-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
calculateSummary(findings) {
const summary = {
totalFindings: findings.length,
criticalCount: 0,
highCount: 0,
mediumCount: 0,
lowCount: 0
};
for (const finding of findings) {
switch (finding.severity.toUpperCase()) {
case 'CRITICAL':
summary.criticalCount++;
break;
case 'HIGH':
summary.highCount++;
break;
case 'MEDIUM':
summary.mediumCount++;
break;
case 'LOW':
summary.lowCount++;
break;
}
}
return summary;
}
severityToSarifLevel(severity) {
const mapping = {
'CRITICAL': 'error',
'HIGH': 'error',
'MEDIUM': 'warning',
'LOW': 'note'
};
return mapping[severity.toUpperCase()] || 'note';
}
}
exports.SecurityScanner = SecurityScanner;
//# sourceMappingURL=security-scanner.js.map