claude-flow-novice 2.0.3 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli/commands/guidance.js +487 -668
- package/dist/src/cli/commands/index-validate.js +18 -29
- package/dist/src/cli/commands/mcp-troubleshoot.js +230 -282
- package/dist/src/cli/commands/neural-goal-init.js +92 -125
- package/dist/src/cli/commands/swarm-exec.js +317 -393
- package/dist/src/cli/commands/swarm.js +1 -1
- package/dist/src/cli/commands/validate-framework.js +983 -1100
- package/dist/src/cli/commands/validate.js +144 -223
- package/dist/src/cli/simple-commands/__tests__/agent.test.js +265 -277
- package/dist/src/cli/simple-commands/__tests__/memory.test.js +6 -7
- package/dist/src/cli/simple-commands/__tests__/swarm.test.js +373 -356
- package/dist/src/cli/simple-commands/__tests__/task.test.js +6 -7
- package/dist/src/cli/simple-commands/agent.js +157 -193
- package/dist/src/cli/simple-commands/analysis.js +336 -446
- package/dist/src/cli/simple-commands/automation-executor.js +1095 -1339
- package/dist/src/cli/simple-commands/automation.js +481 -469
- package/dist/src/cli/simple-commands/batch-manager.js +261 -313
- package/dist/src/cli/simple-commands/claude-telemetry.js +241 -267
- package/dist/src/cli/simple-commands/claude-track.js +68 -90
- package/dist/src/cli/simple-commands/concurrent-display.js +266 -320
- package/dist/src/cli/simple-commands/config.js +245 -290
- package/dist/src/cli/simple-commands/coordination.js +182 -234
- package/dist/src/cli/simple-commands/enhanced-ui-views.js +812 -615
- package/dist/src/cli/simple-commands/enhanced-webui-complete.js +922 -981
- package/dist/src/cli/simple-commands/fix-hook-variables.js +274 -294
- package/dist/src/cli/simple-commands/github/gh-coordinator.js +378 -457
- package/dist/src/cli/simple-commands/github/github-api.js +535 -574
- package/dist/src/cli/simple-commands/github/init.js +276 -303
- package/dist/src/cli/simple-commands/github.js +222 -247
- package/dist/src/cli/simple-commands/goal.js +51 -63
- package/dist/src/cli/simple-commands/hive-mind/auto-save-middleware.js +208 -278
- package/dist/src/cli/simple-commands/hive-mind/communication.js +601 -696
- package/dist/src/cli/simple-commands/hive-mind/core.js +907 -979
- package/dist/src/cli/simple-commands/hive-mind/db-optimizer.js +406 -655
- package/dist/src/cli/simple-commands/hive-mind/mcp-wrapper.js +1125 -1245
- package/dist/src/cli/simple-commands/hive-mind/memory.js +854 -1090
- package/dist/src/cli/simple-commands/hive-mind/performance-optimizer.js +459 -574
- package/dist/src/cli/simple-commands/hive-mind/performance-test.js +263 -347
- package/dist/src/cli/simple-commands/hive-mind/queen.js +727 -768
- package/dist/src/cli/simple-commands/hive-mind/session-manager.js +745 -1049
- package/dist/src/cli/simple-commands/hive-mind-optimize.js +227 -283
- package/dist/src/cli/simple-commands/hive-mind-wizard.js +174 -217
- package/dist/src/cli/simple-commands/hive-mind.js +1842 -2283
- package/dist/src/cli/simple-commands/hive.js +90 -79
- package/dist/src/cli/simple-commands/hook-safety.js +431 -521
- package/dist/src/cli/simple-commands/hooks/session-start-soul.js +203 -254
- package/dist/src/cli/simple-commands/hooks.js +1064 -1204
- package/dist/src/cli/simple-commands/init/agent-copier.js +294 -319
- package/dist/src/cli/simple-commands/init/batch-init.js +496 -562
- package/dist/src/cli/simple-commands/init/claude-commands/claude-flow-commands.js +13 -19
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-claude-flow-commands.js +13 -19
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-slash-commands.js +61 -88
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-sparc-commands.js +125 -150
- package/dist/src/cli/simple-commands/init/claude-commands/slash-commands.js +42 -49
- package/dist/src/cli/simple-commands/init/claude-commands/sparc-commands.js +43 -61
- package/dist/src/cli/simple-commands/init/copy-revised-templates.js +141 -147
- package/dist/src/cli/simple-commands/init/executable-wrapper.js +31 -44
- package/dist/src/cli/simple-commands/init/gitignore-updater.js +64 -90
- package/dist/src/cli/simple-commands/init/help.js +104 -107
- package/dist/src/cli/simple-commands/init/hive-mind-init.js +509 -528
- package/dist/src/cli/simple-commands/init/index.js +1510 -1759
- package/dist/src/cli/simple-commands/init/performance-monitor.js +234 -317
- package/dist/src/cli/simple-commands/init/rollback/backup-manager.js +441 -504
- package/dist/src/cli/simple-commands/init/rollback/index.js +289 -364
- package/dist/src/cli/simple-commands/init/rollback/recovery-manager.js +652 -728
- package/dist/src/cli/simple-commands/init/rollback/rollback-executor.js +416 -481
- package/dist/src/cli/simple-commands/init/rollback/state-tracker.js +369 -448
- package/dist/src/cli/simple-commands/init/sparc/roo-readme.js +1 -2
- package/dist/src/cli/simple-commands/init/sparc/roomodes-config.js +122 -99
- package/dist/src/cli/simple-commands/init/sparc/workflows.js +32 -37
- package/dist/src/cli/simple-commands/init/sparc-structure.js +55 -62
- package/dist/src/cli/simple-commands/init/template-copier.js +421 -533
- package/dist/src/cli/simple-commands/init/templates/coordination-md.js +3 -6
- package/dist/src/cli/simple-commands/init/templates/enhanced-templates.js +344 -318
- package/dist/src/cli/simple-commands/init/templates/github-safe-enhanced.js +173 -218
- package/dist/src/cli/simple-commands/init/templates/github-safe.js +65 -75
- package/dist/src/cli/simple-commands/init/templates/memory-bank-md.js +3 -6
- package/dist/src/cli/simple-commands/init/templates/readme-files.js +2 -4
- package/dist/src/cli/simple-commands/init/templates/safe-hook-patterns.js +187 -230
- package/dist/src/cli/simple-commands/init/templates/sparc-modes.js +53 -80
- package/dist/src/cli/simple-commands/init/templates/verification-claude-md.js +101 -85
- package/dist/src/cli/simple-commands/init/validation/config-validator.js +283 -330
- package/dist/src/cli/simple-commands/init/validation/health-checker.js +495 -561
- package/dist/src/cli/simple-commands/init/validation/index.js +302 -358
- package/dist/src/cli/simple-commands/init/validation/mode-validator.js +308 -359
- package/dist/src/cli/simple-commands/init/validation/post-init-validator.js +389 -366
- package/dist/src/cli/simple-commands/init/validation/pre-init-validator.js +270 -268
- package/dist/src/cli/simple-commands/init/validation/test-runner.js +427 -447
- package/dist/src/cli/simple-commands/init.js +1 -2
- package/dist/src/cli/simple-commands/mcp-health.js +131 -158
- package/dist/src/cli/simple-commands/mcp-integration-layer.js +533 -634
- package/dist/src/cli/simple-commands/mcp.js +345 -400
- package/dist/src/cli/simple-commands/memory-consolidation.js +426 -537
- package/dist/src/cli/simple-commands/memory.js +247 -311
- package/dist/src/cli/simple-commands/migrate-hooks.js +39 -46
- package/dist/src/cli/simple-commands/monitor.js +294 -363
- package/dist/src/cli/simple-commands/neural.js +51 -65
- package/dist/src/cli/simple-commands/pair-autofix-only.js +538 -662
- package/dist/src/cli/simple-commands/pair-basic.js +528 -656
- package/dist/src/cli/simple-commands/pair-old.js +430 -543
- package/dist/src/cli/simple-commands/pair-working.js +615 -751
- package/dist/src/cli/simple-commands/pair.js +615 -751
- package/dist/src/cli/simple-commands/performance-hooks.js +83 -111
- package/dist/src/cli/simple-commands/performance-metrics.js +348 -433
- package/dist/src/cli/simple-commands/process-ui-enhanced.js +708 -787
- package/dist/src/cli/simple-commands/process-ui.js +230 -254
- package/dist/src/cli/simple-commands/realtime-update-system.js +525 -611
- package/dist/src/cli/simple-commands/sparc/architecture.js +1704 -1530
- package/dist/src/cli/simple-commands/sparc/commands.js +438 -516
- package/dist/src/cli/simple-commands/sparc/completion.js +1224 -1481
- package/dist/src/cli/simple-commands/sparc/coordinator.js +913 -978
- package/dist/src/cli/simple-commands/sparc/index.js +241 -298
- package/dist/src/cli/simple-commands/sparc/phase-base.js +314 -390
- package/dist/src/cli/simple-commands/sparc/pseudocode.js +965 -869
- package/dist/src/cli/simple-commands/sparc/refinement.js +980 -1273
- package/dist/src/cli/simple-commands/sparc/specification.js +559 -645
- package/dist/src/cli/simple-commands/sparc-modes/architect.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/ask.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/code.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/debug.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/devops.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/docs-writer.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/generic.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/index.js +47 -55
- package/dist/src/cli/simple-commands/sparc-modes/integration.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/mcp.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/monitoring.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/optimization.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/security-review.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/sparc-orchestrator.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/spec-pseudocode.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/supabase-admin.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/swarm.js +101 -87
- package/dist/src/cli/simple-commands/sparc-modes/tdd.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/tutorial.js +1 -1
- package/dist/src/cli/simple-commands/sparc.js +465 -493
- package/dist/src/cli/simple-commands/start-ui.js +108 -132
- package/dist/src/cli/simple-commands/start-wrapper.js +240 -268
- package/dist/src/cli/simple-commands/start.js +1 -1
- package/dist/src/cli/simple-commands/status.js +254 -275
- package/dist/src/cli/simple-commands/stream-chain-clean.js +128 -171
- package/dist/src/cli/simple-commands/stream-chain-fixed.js +61 -82
- package/dist/src/cli/simple-commands/stream-chain-real.js +267 -331
- package/dist/src/cli/simple-commands/stream-chain-working.js +211 -263
- package/dist/src/cli/simple-commands/stream-chain.js +260 -318
- package/dist/src/cli/simple-commands/stream-processor.js +290 -315
- package/dist/src/cli/simple-commands/swarm-executor.js +189 -222
- package/dist/src/cli/simple-commands/swarm-metrics-integration.js +208 -300
- package/dist/src/cli/simple-commands/swarm-ui.js +623 -703
- package/dist/src/cli/simple-commands/swarm-webui-integration.js +258 -286
- package/dist/src/cli/simple-commands/swarm.js +887 -1082
- package/dist/src/cli/simple-commands/task.js +161 -206
- package/dist/src/cli/simple-commands/timestamp-fix.js +59 -89
- package/dist/src/cli/simple-commands/token-tracker.js +258 -316
- package/dist/src/cli/simple-commands/tool-execution-framework.js +433 -519
- package/dist/src/cli/simple-commands/train-and-stream.js +275 -331
- package/dist/src/cli/simple-commands/training-pipeline.js +619 -725
- package/dist/src/cli/simple-commands/training.js +170 -227
- package/dist/src/cli/simple-commands/verification-hooks.js +261 -284
- package/dist/src/cli/simple-commands/verification-integration.js +389 -417
- package/dist/src/cli/simple-commands/verification-training-integration.js +486 -606
- package/dist/src/cli/simple-commands/verification.js +493 -513
- package/dist/src/cli/simple-commands/web-server.js +766 -836
- package/dist/src/cli/simple-commands/webui-validator.js +106 -124
- package/dist/src/coordination/event-bus/demo-wasm-integration.js +212 -251
- package/dist/src/coordination/event-bus/qe-event-bus.js +608 -748
- package/dist/src/coordination/event-bus/qe-event-bus.test.js +379 -454
- package/dist/src/coordination/iteration-tracker.js +363 -454
- package/dist/src/enterprise/analytics-manager.js +1135 -0
- package/dist/src/enterprise/audit-manager.js +1115 -0
- package/dist/src/enterprise/cloud-manager.js +891 -0
- package/dist/src/enterprise/deployment-manager.js +966 -0
- package/dist/src/enterprise/index.js +6 -0
- package/dist/src/enterprise/project-manager.js +584 -0
- package/dist/src/enterprise/security-manager.js +991 -0
- package/dist/src/index.js +1 -1
- package/dist/src/mcp/DEPRECATED.js +46 -60
- package/dist/src/mcp/fixes/mcp-error-fixes.js +115 -134
- package/dist/src/mcp/implementations/agent-tracker.js +114 -128
- package/dist/src/mcp/implementations/daa-tools.js +292 -350
- package/dist/src/mcp/implementations/workflow-tools.js +329 -361
- package/dist/src/mcp/mcp-config-manager.js +1183 -1331
- package/dist/src/mcp/mcp-server-novice-simplified.js +11 -17
- package/dist/src/mcp/mcp-server-novice.js +11 -17
- package/dist/src/mcp/mcp-server-sdk.js +11 -17
- package/dist/src/mcp/mcp-server.js +1620 -1484
- package/dist/src/mcp/ruv-swarm-wrapper.js +209 -239
- package/dist/src/memory/advanced-serializer.js +609 -589
- package/dist/src/memory/enhanced-examples.js +220 -305
- package/dist/src/memory/enhanced-memory.js +295 -336
- package/dist/src/memory/enhanced-session-serializer.js +408 -492
- package/dist/src/memory/fallback-memory-system.js +900 -1021
- package/dist/src/memory/fallback-store.js +93 -131
- package/dist/src/memory/high-performance-serialization.js +592 -730
- package/dist/src/memory/in-memory-store.js +161 -213
- package/dist/src/memory/index.js +123 -157
- package/dist/src/memory/lock-free-structures.js +578 -764
- package/dist/src/memory/memory-mapped-persistence.js +585 -766
- package/dist/src/memory/memory-pressure-manager.js +569 -707
- package/dist/src/memory/migration.js +358 -445
- package/dist/src/memory/shared-memory.js +641 -768
- package/dist/src/memory/sqlite-store.js +245 -325
- package/dist/src/memory/sqlite-wrapper.js +122 -151
- package/dist/src/memory/swarm-memory.js +470 -603
- package/dist/src/memory/test-example.js +126 -134
- package/dist/src/memory/ultra-fast-memory-store.js +622 -821
- package/dist/src/memory/unified-memory-manager.js +356 -437
- package/dist/src/migration/index.js +92 -0
- package/dist/src/migration/logger.js +121 -0
- package/dist/src/migration/migration-analyzer.js +268 -0
- package/dist/src/migration/migration-runner.js +522 -0
- package/dist/src/migration/migration-validator.js +285 -0
- package/dist/src/migration/progress-reporter.js +150 -0
- package/dist/src/migration/rollback-manager.js +321 -0
- package/dist/src/migration/tests/migration-system.test.js +7 -0
- package/dist/src/migration/types.js +3 -0
- package/dist/src/swarm/CodeRefactoringSwarm.js +777 -952
- package/dist/src/swarm/__tests__/integration.test.js +227 -0
- package/dist/src/swarm/__tests__/prompt-copier.test.js +344 -0
- package/dist/src/swarm/advanced-orchestrator.js +1095 -0
- package/dist/src/swarm/claude-code-interface.js +961 -0
- package/dist/src/swarm/claude-flow-executor.js +229 -0
- package/dist/src/swarm/consensus-coordinator.js +475 -0
- package/dist/src/swarm/coordinator.js +2993 -0
- package/dist/src/swarm/direct-executor.js +1180 -0
- package/dist/src/swarm/error-recovery/advanced-error-detection.js +691 -0
- package/dist/src/swarm/error-recovery/automated-recovery-workflows.js +998 -0
- package/dist/src/swarm/error-recovery/error-recovery-coordinator.js +1197 -0
- package/dist/src/swarm/error-recovery/recovery-monitoring.js +772 -0
- package/dist/src/swarm/error-recovery/resilience-architecture.js +714 -0
- package/dist/src/swarm/error-recovery/self-healing-mechanisms.js +1319 -0
- package/dist/src/swarm/error-recovery/test-error-recovery-effectiveness.js +808 -0
- package/dist/src/swarm/executor-v2.js +322 -0
- package/dist/src/swarm/executor.js +815 -0
- package/dist/src/swarm/hive-mind-integration.js +703 -0
- package/dist/src/swarm/index.js +41 -0
- package/dist/src/swarm/json-output-aggregator.js +267 -0
- package/dist/src/swarm/large-scale-coordinator.js +542 -0
- package/dist/src/swarm/mcp-integration-wrapper.js +628 -0
- package/dist/src/swarm/memory.js +1117 -0
- package/dist/src/swarm/optimizations/__tests__/optimization.test.js +348 -0
- package/dist/src/swarm/optimizations/async-file-manager.js +285 -0
- package/dist/src/swarm/optimizations/circular-buffer.js +162 -0
- package/dist/src/swarm/optimizations/connection-pool.js +244 -0
- package/dist/src/swarm/optimizations/index.js +28 -0
- package/dist/src/swarm/optimizations/optimized-executor.js +320 -0
- package/dist/src/swarm/optimizations/ttl-map.js +234 -0
- package/dist/src/swarm/prompt-cli.js +200 -0
- package/dist/src/swarm/prompt-copier-enhanced.js +202 -0
- package/dist/src/swarm/prompt-copier.js +381 -0
- package/dist/src/swarm/prompt-manager.js +295 -0
- package/dist/src/swarm/prompt-utils.js +310 -0
- package/dist/src/swarm/result-aggregator.js +718 -0
- package/dist/src/swarm/sparc-executor.js +1568 -0
- package/dist/src/swarm/strategies/auto.js +758 -0
- package/dist/src/swarm/strategies/base.js +128 -0
- package/dist/src/swarm/strategies/research.js +914 -0
- package/dist/src/swarm/strategies/strategy-metrics-patch.js +2 -0
- package/dist/src/swarm/types.js +52 -0
- package/dist/src/swarm/workers/copy-worker.js +56 -0
- package/dist/src/utils/__tests__/github-cli-safety-wrapper.test.js +332 -400
- package/dist/src/utils/github-cli-safe.js +56 -64
- package/dist/src/utils/github-cli-safety-wrapper.js +451 -546
- package/dist/src/utils/npx-isolated-cache.js +104 -119
- package/dist/src/utils/preference-manager.js +622 -652
- package/dist/src/utils/timezone-utils.js +86 -105
- package/dist/src/validators/epic-config-schema.js +214 -0
- package/dist/src/validators/index.js +10 -0
- package/dist/src/validators/swarm-init-validator.js +259 -0
- package/dist/src/validators/todowrite-batching-validator.js +215 -0
- package/dist/src/validators/todowrite-integration.js +187 -0
- package/package.json +2 -2
|
@@ -0,0 +1,991 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
import { EventEmitter } from "events";
|
|
15
|
+
import { writeFile, readFile, mkdir, readdir } from "node:fs/promises";
|
|
16
|
+
import { join } from "path";
|
|
17
|
+
import { spawn } from "child_process";
|
|
18
|
+
import { Logger } from "../core/logger.js";
|
|
19
|
+
import { ConfigManager } from "../core/config.js";
|
|
20
|
+
export class SecurityManager extends EventEmitter {
|
|
21
|
+
async initialize() {
|
|
22
|
+
try {
|
|
23
|
+
await mkdir(this.securityPath, {
|
|
24
|
+
recursive: true
|
|
25
|
+
});
|
|
26
|
+
await mkdir(join(this.securityPath, 'scans'), {
|
|
27
|
+
recursive: true
|
|
28
|
+
});
|
|
29
|
+
await mkdir(join(this.securityPath, 'policies'), {
|
|
30
|
+
recursive: true
|
|
31
|
+
});
|
|
32
|
+
await mkdir(join(this.securityPath, 'incidents'), {
|
|
33
|
+
recursive: true
|
|
34
|
+
});
|
|
35
|
+
await mkdir(join(this.securityPath, 'reports'), {
|
|
36
|
+
recursive: true
|
|
37
|
+
});
|
|
38
|
+
await mkdir(join(this.securityPath, 'databases'), {
|
|
39
|
+
recursive: true
|
|
40
|
+
});
|
|
41
|
+
await this.loadConfigurations();
|
|
42
|
+
await this.initializeDefaultPolicies();
|
|
43
|
+
await this.initializeVulnerabilityDatabases();
|
|
44
|
+
this.logger.info('Security Manager initialized successfully');
|
|
45
|
+
} catch (error) {
|
|
46
|
+
this.logger.error('Failed to initialize Security Manager', {
|
|
47
|
+
error
|
|
48
|
+
});
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async createSecurityScan(scanData) {
|
|
53
|
+
const scan = {
|
|
54
|
+
id: `scan-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
55
|
+
name: scanData.name,
|
|
56
|
+
type: scanData.type,
|
|
57
|
+
status: 'pending',
|
|
58
|
+
projectId: scanData.projectId,
|
|
59
|
+
target: scanData.target,
|
|
60
|
+
configuration: {
|
|
61
|
+
scanner: this.getDefaultScanner(scanData.type),
|
|
62
|
+
rules: [],
|
|
63
|
+
excludes: [],
|
|
64
|
+
severity: [
|
|
65
|
+
'critical',
|
|
66
|
+
'high',
|
|
67
|
+
'medium',
|
|
68
|
+
'low'
|
|
69
|
+
],
|
|
70
|
+
formats: [
|
|
71
|
+
'json',
|
|
72
|
+
'html'
|
|
73
|
+
],
|
|
74
|
+
outputPath: join(this.securityPath, 'reports'),
|
|
75
|
+
...scanData.configuration
|
|
76
|
+
},
|
|
77
|
+
results: [],
|
|
78
|
+
metrics: {
|
|
79
|
+
totalFindings: 0,
|
|
80
|
+
criticalFindings: 0,
|
|
81
|
+
highFindings: 0,
|
|
82
|
+
mediumFindings: 0,
|
|
83
|
+
lowFindings: 0,
|
|
84
|
+
falsePositives: 0,
|
|
85
|
+
suppressed: 0,
|
|
86
|
+
scanDuration: 0,
|
|
87
|
+
filesScanned: 0,
|
|
88
|
+
linesScanned: 0
|
|
89
|
+
},
|
|
90
|
+
compliance: {
|
|
91
|
+
frameworks: [],
|
|
92
|
+
requirements: [],
|
|
93
|
+
overallScore: 0,
|
|
94
|
+
passedChecks: 0,
|
|
95
|
+
failedChecks: 0
|
|
96
|
+
},
|
|
97
|
+
remediation: {
|
|
98
|
+
autoFixAvailable: [],
|
|
99
|
+
manualReview: [],
|
|
100
|
+
recommendations: []
|
|
101
|
+
},
|
|
102
|
+
schedule: scanData.schedule,
|
|
103
|
+
notifications: {
|
|
104
|
+
channels: [],
|
|
105
|
+
thresholds: {
|
|
106
|
+
critical: 1,
|
|
107
|
+
high: 5,
|
|
108
|
+
medium: 10
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
createdAt: new Date(),
|
|
112
|
+
updatedAt: new Date(),
|
|
113
|
+
createdBy: 'system',
|
|
114
|
+
auditLog: []
|
|
115
|
+
};
|
|
116
|
+
this.addAuditEntry(scan, 'system', 'scan_created', 'scan', {
|
|
117
|
+
scanId: scan.id,
|
|
118
|
+
scanName: scan.name,
|
|
119
|
+
scanType: scan.type
|
|
120
|
+
});
|
|
121
|
+
this.scans.set(scan.id, scan);
|
|
122
|
+
await this.saveScan(scan);
|
|
123
|
+
this.emit('scan:created', scan);
|
|
124
|
+
this.logger.info(`Security scan created: ${scan.name} (${scan.id})`);
|
|
125
|
+
return scan;
|
|
126
|
+
}
|
|
127
|
+
async executeScan(scanId) {
|
|
128
|
+
const scan = this.scans.get(scanId);
|
|
129
|
+
if (!scan) {
|
|
130
|
+
throw new Error(`Scan not found: ${scanId}`);
|
|
131
|
+
}
|
|
132
|
+
if (scan.status !== 'pending') {
|
|
133
|
+
throw new Error(`Scan ${scanId} is not in pending status`);
|
|
134
|
+
}
|
|
135
|
+
scan.status = 'running';
|
|
136
|
+
scan.updatedAt = new Date();
|
|
137
|
+
this.addAuditEntry(scan, 'system', 'scan_started', 'scan', {
|
|
138
|
+
scanId,
|
|
139
|
+
target: scan.target
|
|
140
|
+
});
|
|
141
|
+
await this.saveScan(scan);
|
|
142
|
+
this.emit('scan:started', scan);
|
|
143
|
+
try {
|
|
144
|
+
const startTime = Date.now();
|
|
145
|
+
// Execute the appropriate scanner
|
|
146
|
+
const findings = await this.executeScanEngine(scan);
|
|
147
|
+
const endTime = Date.now();
|
|
148
|
+
scan.metrics.scanDuration = endTime - startTime;
|
|
149
|
+
scan.results = findings;
|
|
150
|
+
scan.status = 'completed';
|
|
151
|
+
// Calculate metrics
|
|
152
|
+
this.calculateScanMetrics(scan);
|
|
153
|
+
// Run compliance checks
|
|
154
|
+
await this.runComplianceChecks(scan);
|
|
155
|
+
// Generate remediation recommendations
|
|
156
|
+
await this.generateRemediationRecommendations(scan);
|
|
157
|
+
// Check notification thresholds
|
|
158
|
+
await this.checkNotificationThresholds(scan);
|
|
159
|
+
scan.updatedAt = new Date();
|
|
160
|
+
this.addAuditEntry(scan, 'system', 'scan_completed', 'scan', {
|
|
161
|
+
scanId,
|
|
162
|
+
duration: scan.metrics.scanDuration,
|
|
163
|
+
findingsCount: scan.results.length
|
|
164
|
+
});
|
|
165
|
+
await this.saveScan(scan);
|
|
166
|
+
this.emit('scan:completed', scan);
|
|
167
|
+
this.logger.info(`Security scan completed: ${scan.name} (${scan.id}) - ${scan.results.length} findings`);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
scan.status = 'failed';
|
|
170
|
+
scan.updatedAt = new Date();
|
|
171
|
+
this.addAuditEntry(scan, 'system', 'scan_failed', 'scan', {
|
|
172
|
+
scanId,
|
|
173
|
+
error: error instanceof Error ? error.message : String(error)
|
|
174
|
+
});
|
|
175
|
+
await this.saveScan(scan);
|
|
176
|
+
this.emit('scan:failed', {
|
|
177
|
+
scan,
|
|
178
|
+
error
|
|
179
|
+
});
|
|
180
|
+
this.logger.error(`Security scan failed: ${scan.name} (${scanId})`, {
|
|
181
|
+
error
|
|
182
|
+
});
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async createSecurityIncident(incidentData) {
|
|
187
|
+
const incident = {
|
|
188
|
+
id: `incident-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
189
|
+
title: incidentData.title,
|
|
190
|
+
description: incidentData.description,
|
|
191
|
+
severity: incidentData.severity,
|
|
192
|
+
status: 'open',
|
|
193
|
+
type: incidentData.type,
|
|
194
|
+
source: incidentData.source,
|
|
195
|
+
affected: {
|
|
196
|
+
systems: [],
|
|
197
|
+
data: [],
|
|
198
|
+
users: [],
|
|
199
|
+
...incidentData.affected
|
|
200
|
+
},
|
|
201
|
+
timeline: {
|
|
202
|
+
detected: new Date(),
|
|
203
|
+
reported: new Date(),
|
|
204
|
+
acknowledged: new Date()
|
|
205
|
+
},
|
|
206
|
+
response: {
|
|
207
|
+
assignedTo: [],
|
|
208
|
+
actions: [],
|
|
209
|
+
communications: [],
|
|
210
|
+
lessons: []
|
|
211
|
+
},
|
|
212
|
+
evidence: {
|
|
213
|
+
logs: [],
|
|
214
|
+
files: [],
|
|
215
|
+
screenshots: [],
|
|
216
|
+
forensics: []
|
|
217
|
+
},
|
|
218
|
+
impact: {
|
|
219
|
+
confidentiality: 'none',
|
|
220
|
+
integrity: 'none',
|
|
221
|
+
availability: 'none'
|
|
222
|
+
},
|
|
223
|
+
rootCause: {
|
|
224
|
+
primary: '',
|
|
225
|
+
contributing: [],
|
|
226
|
+
analysis: ''
|
|
227
|
+
},
|
|
228
|
+
remediation: {
|
|
229
|
+
immediate: [],
|
|
230
|
+
shortTerm: [],
|
|
231
|
+
longTerm: [],
|
|
232
|
+
preventive: []
|
|
233
|
+
},
|
|
234
|
+
createdAt: new Date(),
|
|
235
|
+
updatedAt: new Date(),
|
|
236
|
+
createdBy: 'system',
|
|
237
|
+
auditLog: []
|
|
238
|
+
};
|
|
239
|
+
this.addAuditEntry(incident, 'system', 'incident_created', 'incident', {
|
|
240
|
+
incidentId: incident.id,
|
|
241
|
+
severity: incident.severity,
|
|
242
|
+
type: incident.type
|
|
243
|
+
});
|
|
244
|
+
this.incidents.set(incident.id, incident);
|
|
245
|
+
await this.saveIncident(incident);
|
|
246
|
+
// Auto-assign based on severity and type
|
|
247
|
+
await this.autoAssignIncident(incident);
|
|
248
|
+
// Send immediate notifications for high/critical incidents
|
|
249
|
+
if (incident.severity === 'critical' || incident.severity === 'high') {
|
|
250
|
+
await this.sendIncidentNotification(incident);
|
|
251
|
+
}
|
|
252
|
+
this.emit('incident:created', incident);
|
|
253
|
+
this.logger.info(`Security incident created: ${incident.title} (${incident.id})`);
|
|
254
|
+
return incident;
|
|
255
|
+
}
|
|
256
|
+
async updateIncident(incidentId, updates, userId = 'system') {
|
|
257
|
+
const incident = this.incidents.get(incidentId);
|
|
258
|
+
if (!incident) {
|
|
259
|
+
throw new Error(`Incident not found: ${incidentId}`);
|
|
260
|
+
}
|
|
261
|
+
const oldStatus = incident.status;
|
|
262
|
+
Object.assign(incident, updates);
|
|
263
|
+
incident.updatedAt = new Date();
|
|
264
|
+
// Update timeline based on status changes
|
|
265
|
+
if (updates.status && updates.status !== oldStatus) {
|
|
266
|
+
this.updateIncidentTimeline(incident, updates.status);
|
|
267
|
+
}
|
|
268
|
+
this.addAuditEntry(incident, userId, 'incident_updated', 'incident', {
|
|
269
|
+
incidentId,
|
|
270
|
+
changes: Object.keys(updates),
|
|
271
|
+
oldStatus,
|
|
272
|
+
newStatus: incident.status
|
|
273
|
+
});
|
|
274
|
+
await this.saveIncident(incident);
|
|
275
|
+
this.emit('incident:updated', {
|
|
276
|
+
incident,
|
|
277
|
+
updates
|
|
278
|
+
});
|
|
279
|
+
this.logger.info(`Security incident updated: ${incident.title} (${incidentId})`);
|
|
280
|
+
return incident;
|
|
281
|
+
}
|
|
282
|
+
async runComplianceAssessment(frameworks, scope) {
|
|
283
|
+
const checks = [];
|
|
284
|
+
for (const framework of frameworks){
|
|
285
|
+
const frameworkChecks = await this.runFrameworkChecks(framework, scope);
|
|
286
|
+
checks.push(...frameworkChecks);
|
|
287
|
+
}
|
|
288
|
+
this.logger.info(`Compliance assessment completed: ${checks.length} checks across ${frameworks.length} frameworks`);
|
|
289
|
+
this.emit('compliance:assessed', {
|
|
290
|
+
frameworks,
|
|
291
|
+
checks,
|
|
292
|
+
scope
|
|
293
|
+
});
|
|
294
|
+
return checks;
|
|
295
|
+
}
|
|
296
|
+
async createSecurityPolicy(policyData) {
|
|
297
|
+
const policy = {
|
|
298
|
+
id: `policy-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
299
|
+
name: policyData.name,
|
|
300
|
+
description: policyData.description,
|
|
301
|
+
type: policyData.type,
|
|
302
|
+
version: '1.0.0',
|
|
303
|
+
status: 'draft',
|
|
304
|
+
rules: policyData.rules.map((rule)=>({
|
|
305
|
+
id: `rule-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
306
|
+
...rule
|
|
307
|
+
})),
|
|
308
|
+
enforcement: {
|
|
309
|
+
level: 'warning',
|
|
310
|
+
exceptions: [],
|
|
311
|
+
approvers: [],
|
|
312
|
+
...policyData.enforcement
|
|
313
|
+
},
|
|
314
|
+
applicability: {
|
|
315
|
+
projects: [],
|
|
316
|
+
environments: [],
|
|
317
|
+
resources: [],
|
|
318
|
+
...policyData.applicability
|
|
319
|
+
},
|
|
320
|
+
schedule: {
|
|
321
|
+
reviewFrequency: 'annually',
|
|
322
|
+
nextReview: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000),
|
|
323
|
+
reviewer: 'security-team'
|
|
324
|
+
},
|
|
325
|
+
metrics: {
|
|
326
|
+
violations: 0,
|
|
327
|
+
compliance: 100,
|
|
328
|
+
exceptions: 0
|
|
329
|
+
},
|
|
330
|
+
createdAt: new Date(),
|
|
331
|
+
updatedAt: new Date(),
|
|
332
|
+
createdBy: 'system'
|
|
333
|
+
};
|
|
334
|
+
this.policies.set(policy.id, policy);
|
|
335
|
+
await this.savePolicy(policy);
|
|
336
|
+
this.emit('policy:created', policy);
|
|
337
|
+
this.logger.info(`Security policy created: ${policy.name} (${policy.id})`);
|
|
338
|
+
return policy;
|
|
339
|
+
}
|
|
340
|
+
async getSecurityMetrics(filters) {
|
|
341
|
+
let scans = Array.from(this.scans.values());
|
|
342
|
+
let incidents = Array.from(this.incidents.values());
|
|
343
|
+
// Apply filters
|
|
344
|
+
if (filters) {
|
|
345
|
+
if (filters.timeRange) {
|
|
346
|
+
scans = scans.filter((s)=>s.createdAt >= filters.timeRange.start && s.createdAt <= filters.timeRange.end);
|
|
347
|
+
incidents = incidents.filter((i)=>i.createdAt >= filters.timeRange.start && i.createdAt <= filters.timeRange.end);
|
|
348
|
+
}
|
|
349
|
+
if (filters.projectId) {
|
|
350
|
+
scans = scans.filter((s)=>s.projectId === filters.projectId);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Calculate scan metrics
|
|
354
|
+
const scanMetrics = {
|
|
355
|
+
total: scans.length,
|
|
356
|
+
completed: scans.filter((s)=>s.status === 'completed').length,
|
|
357
|
+
failed: scans.filter((s)=>s.status === 'failed').length,
|
|
358
|
+
inProgress: scans.filter((s)=>s.status === 'running').length,
|
|
359
|
+
byType: this.groupBy(scans, 'type'),
|
|
360
|
+
averageDuration: scans.length > 0 ? scans.reduce((sum, s)=>sum + s.metrics.scanDuration, 0) / scans.length : 0
|
|
361
|
+
};
|
|
362
|
+
// Calculate finding metrics
|
|
363
|
+
const allFindings = scans.flatMap((s)=>s.results);
|
|
364
|
+
const findingMetrics = {
|
|
365
|
+
total: allFindings.length,
|
|
366
|
+
open: allFindings.filter((f)=>f.status === 'open').length,
|
|
367
|
+
resolved: allFindings.filter((f)=>f.status === 'resolved').length,
|
|
368
|
+
suppressed: allFindings.filter((f)=>f.status === 'suppressed').length,
|
|
369
|
+
bySeverity: this.groupBy(allFindings, 'severity'),
|
|
370
|
+
byCategory: this.groupBy(allFindings, 'category'),
|
|
371
|
+
meanTimeToResolution: this.calculateMTTR(allFindings)
|
|
372
|
+
};
|
|
373
|
+
// Calculate compliance metrics
|
|
374
|
+
const allComplianceChecks = scans.flatMap((s)=>s.compliance.requirements);
|
|
375
|
+
const complianceFrameworks = {};
|
|
376
|
+
for (const check of allComplianceChecks){
|
|
377
|
+
if (!complianceFrameworks[check.framework]) {
|
|
378
|
+
complianceFrameworks[check.framework] = {
|
|
379
|
+
total: 0,
|
|
380
|
+
passed: 0,
|
|
381
|
+
failed: 0,
|
|
382
|
+
score: 0
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
complianceFrameworks[check.framework].total++;
|
|
386
|
+
if (check.status === 'passed') {
|
|
387
|
+
complianceFrameworks[check.framework].passed++;
|
|
388
|
+
} else if (check.status === 'failed') {
|
|
389
|
+
complianceFrameworks[check.framework].failed++;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Calculate scores
|
|
393
|
+
for(const framework in complianceFrameworks){
|
|
394
|
+
const fw = complianceFrameworks[framework];
|
|
395
|
+
fw.score = fw.total > 0 ? fw.passed / fw.total * 100 : 0;
|
|
396
|
+
}
|
|
397
|
+
const overallComplianceScore = Object.values(complianceFrameworks).length > 0 ? Object.values(complianceFrameworks).reduce((sum, fw)=>sum + fw.score, 0) / Object.values(complianceFrameworks).length : 0;
|
|
398
|
+
// Calculate incident metrics
|
|
399
|
+
const incidentMetrics = {
|
|
400
|
+
total: incidents.length,
|
|
401
|
+
open: incidents.filter((i)=>i.status === 'open' || i.status === 'investigating').length,
|
|
402
|
+
resolved: incidents.filter((i)=>i.status === 'resolved' || i.status === 'closed').length,
|
|
403
|
+
bySeverity: this.groupBy(incidents, 'severity'),
|
|
404
|
+
meanTimeToDetection: this.calculateMTTD(incidents),
|
|
405
|
+
meanTimeToResponse: this.calculateMTTResponse(incidents),
|
|
406
|
+
meanTimeToResolution: this.calculateIncidentMTTR(incidents)
|
|
407
|
+
};
|
|
408
|
+
// Policy metrics
|
|
409
|
+
const policies = Array.from(this.policies.values());
|
|
410
|
+
const policyMetrics = {
|
|
411
|
+
total: policies.length,
|
|
412
|
+
active: policies.filter((p)=>p.status === 'active').length,
|
|
413
|
+
violations: policies.reduce((sum, p)=>sum + p.metrics.violations, 0),
|
|
414
|
+
compliance: policies.length > 0 ? policies.reduce((sum, p)=>sum + p.metrics.compliance, 0) / policies.length : 0
|
|
415
|
+
};
|
|
416
|
+
return {
|
|
417
|
+
scans: scanMetrics,
|
|
418
|
+
findings: findingMetrics,
|
|
419
|
+
compliance: {
|
|
420
|
+
frameworks: complianceFrameworks,
|
|
421
|
+
overallScore: overallComplianceScore,
|
|
422
|
+
trending: 'stable'
|
|
423
|
+
},
|
|
424
|
+
incidents: incidentMetrics,
|
|
425
|
+
policies: policyMetrics,
|
|
426
|
+
trends: {
|
|
427
|
+
findingsTrend: [],
|
|
428
|
+
complianceTrend: [],
|
|
429
|
+
incidentsTrend: []
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
// Private helper methods
|
|
434
|
+
async loadConfigurations() {
|
|
435
|
+
try {
|
|
436
|
+
// Load scans
|
|
437
|
+
const scanFiles = await readdir(join(this.securityPath, 'scans'));
|
|
438
|
+
for (const file of scanFiles.filter((f)=>f.endsWith('.json'))){
|
|
439
|
+
const content = await readFile(join(this.securityPath, 'scans', file), 'utf-8');
|
|
440
|
+
const scan = JSON.parse(content);
|
|
441
|
+
this.scans.set(scan.id, scan);
|
|
442
|
+
}
|
|
443
|
+
// Load policies
|
|
444
|
+
const policyFiles = await readdir(join(this.securityPath, 'policies'));
|
|
445
|
+
for (const file of policyFiles.filter((f)=>f.endsWith('.json'))){
|
|
446
|
+
const content = await readFile(join(this.securityPath, 'policies', file), 'utf-8');
|
|
447
|
+
const policy = JSON.parse(content);
|
|
448
|
+
this.policies.set(policy.id, policy);
|
|
449
|
+
}
|
|
450
|
+
// Load incidents
|
|
451
|
+
const incidentFiles = await readdir(join(this.securityPath, 'incidents'));
|
|
452
|
+
for (const file of incidentFiles.filter((f)=>f.endsWith('.json'))){
|
|
453
|
+
const content = await readFile(join(this.securityPath, 'incidents', file), 'utf-8');
|
|
454
|
+
const incident = JSON.parse(content);
|
|
455
|
+
this.incidents.set(incident.id, incident);
|
|
456
|
+
}
|
|
457
|
+
this.logger.info(`Loaded ${this.scans.size} scans, ${this.policies.size} policies, ${this.incidents.size} incidents`);
|
|
458
|
+
} catch (error) {
|
|
459
|
+
this.logger.warn('Failed to load some security configurations', {
|
|
460
|
+
error
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
async initializeDefaultPolicies() {
|
|
465
|
+
const defaultPolicies = [
|
|
466
|
+
{
|
|
467
|
+
name: 'Critical Vulnerability Policy',
|
|
468
|
+
description: 'Immediate action required for critical vulnerabilities',
|
|
469
|
+
type: 'scanning',
|
|
470
|
+
rules: [
|
|
471
|
+
{
|
|
472
|
+
name: 'Critical CVSS Score',
|
|
473
|
+
description: 'Alert on vulnerabilities with CVSS score >= 9.0',
|
|
474
|
+
condition: 'cvss.score >= 9.0',
|
|
475
|
+
action: 'alert',
|
|
476
|
+
severity: 'critical',
|
|
477
|
+
parameters: {
|
|
478
|
+
threshold: 9.0
|
|
479
|
+
},
|
|
480
|
+
enabled: true
|
|
481
|
+
}
|
|
482
|
+
],
|
|
483
|
+
enforcement: {
|
|
484
|
+
level: 'blocking',
|
|
485
|
+
exceptions: [],
|
|
486
|
+
approvers: [
|
|
487
|
+
'security-lead'
|
|
488
|
+
]
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
name: 'Secret Detection Policy',
|
|
493
|
+
description: 'Detect exposed secrets and credentials',
|
|
494
|
+
type: 'scanning',
|
|
495
|
+
rules: [
|
|
496
|
+
{
|
|
497
|
+
name: 'API Key Detection',
|
|
498
|
+
description: 'Detect exposed API keys',
|
|
499
|
+
condition: 'category == "secret" && type == "api-key"',
|
|
500
|
+
action: 'deny',
|
|
501
|
+
severity: 'high',
|
|
502
|
+
parameters: {},
|
|
503
|
+
enabled: true
|
|
504
|
+
}
|
|
505
|
+
]
|
|
506
|
+
}
|
|
507
|
+
];
|
|
508
|
+
for (const policyData of defaultPolicies){
|
|
509
|
+
if (!Array.from(this.policies.values()).some((p)=>p.name === policyData.name)) {
|
|
510
|
+
await this.createSecurityPolicy(policyData);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
async initializeVulnerabilityDatabases() {
|
|
515
|
+
const databases = [
|
|
516
|
+
{
|
|
517
|
+
id: 'nvd',
|
|
518
|
+
name: 'National Vulnerability Database',
|
|
519
|
+
type: 'nvd',
|
|
520
|
+
url: 'https://nvd.nist.gov/feeds/json/cve/1.1/',
|
|
521
|
+
updateFrequency: 'daily',
|
|
522
|
+
lastUpdate: new Date(),
|
|
523
|
+
status: 'active',
|
|
524
|
+
configuration: {}
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
id: 'github-advisories',
|
|
528
|
+
name: 'GitHub Security Advisories',
|
|
529
|
+
type: 'github',
|
|
530
|
+
url: 'https://api.github.com/advisories',
|
|
531
|
+
updateFrequency: 'daily',
|
|
532
|
+
lastUpdate: new Date(),
|
|
533
|
+
status: 'active',
|
|
534
|
+
configuration: {}
|
|
535
|
+
}
|
|
536
|
+
];
|
|
537
|
+
for (const db of databases){
|
|
538
|
+
this.vulnerabilityDatabases.set(db.id, db);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
getDefaultScanner(type) {
|
|
542
|
+
const scanners = {
|
|
543
|
+
vulnerability: 'trivy',
|
|
544
|
+
dependency: 'npm-audit',
|
|
545
|
+
'code-quality': 'sonarqube',
|
|
546
|
+
secrets: 'gitleaks',
|
|
547
|
+
compliance: 'inspec',
|
|
548
|
+
infrastructure: 'checkov',
|
|
549
|
+
container: 'clair'
|
|
550
|
+
};
|
|
551
|
+
return scanners[type] || 'generic';
|
|
552
|
+
}
|
|
553
|
+
async executeScanEngine(scan) {
|
|
554
|
+
const findings = [];
|
|
555
|
+
switch(scan.configuration.scanner){
|
|
556
|
+
case 'trivy':
|
|
557
|
+
return this.executeTrivyScan(scan);
|
|
558
|
+
case 'npm-audit':
|
|
559
|
+
return this.executeNpmAuditScan(scan);
|
|
560
|
+
case 'gitleaks':
|
|
561
|
+
return this.executeGitleaksScan(scan);
|
|
562
|
+
case 'checkov':
|
|
563
|
+
return this.executeCheckovScan(scan);
|
|
564
|
+
default:
|
|
565
|
+
return this.executeGenericScan(scan);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
async executeTrivyScan(scan) {
|
|
569
|
+
return new Promise((resolve, reject)=>{
|
|
570
|
+
const findings = [];
|
|
571
|
+
// Mock Trivy execution
|
|
572
|
+
const mockFindings = [
|
|
573
|
+
{
|
|
574
|
+
id: `finding-${Date.now()}-1`,
|
|
575
|
+
title: 'CVE-2023-12345: Remote Code Execution in libxml2',
|
|
576
|
+
description: 'A buffer overflow vulnerability in libxml2 allows remote code execution',
|
|
577
|
+
severity: 'critical',
|
|
578
|
+
category: 'vulnerability',
|
|
579
|
+
cve: 'CVE-2023-12345',
|
|
580
|
+
cvss: {
|
|
581
|
+
score: 9.8,
|
|
582
|
+
vector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H',
|
|
583
|
+
version: '3.1'
|
|
584
|
+
},
|
|
585
|
+
location: {
|
|
586
|
+
file: 'package-lock.json',
|
|
587
|
+
line: 125,
|
|
588
|
+
component: 'libxml2@2.9.10'
|
|
589
|
+
},
|
|
590
|
+
evidence: {
|
|
591
|
+
snippet: '"libxml2": "2.9.10"',
|
|
592
|
+
context: 'Dependency declaration',
|
|
593
|
+
references: [
|
|
594
|
+
'https://nvd.nist.gov/vuln/detail/CVE-2023-12345'
|
|
595
|
+
]
|
|
596
|
+
},
|
|
597
|
+
impact: 'Remote attackers could execute arbitrary code',
|
|
598
|
+
remediation: {
|
|
599
|
+
description: 'Update libxml2 to version 2.9.14 or later',
|
|
600
|
+
effort: 'low',
|
|
601
|
+
priority: 'critical',
|
|
602
|
+
autoFixable: true,
|
|
603
|
+
steps: [
|
|
604
|
+
'npm update libxml2'
|
|
605
|
+
],
|
|
606
|
+
references: [
|
|
607
|
+
'https://github.com/GNOME/libxml2/releases'
|
|
608
|
+
]
|
|
609
|
+
},
|
|
610
|
+
status: 'open',
|
|
611
|
+
tags: [
|
|
612
|
+
'cve',
|
|
613
|
+
'rce',
|
|
614
|
+
'dependency'
|
|
615
|
+
],
|
|
616
|
+
metadata: {},
|
|
617
|
+
firstSeen: new Date(),
|
|
618
|
+
lastSeen: new Date(),
|
|
619
|
+
occurrences: 1
|
|
620
|
+
}
|
|
621
|
+
];
|
|
622
|
+
// Simulate scan delay
|
|
623
|
+
setTimeout(()=>{
|
|
624
|
+
resolve(mockFindings);
|
|
625
|
+
}, 2000);
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
async executeNpmAuditScan(scan) {
|
|
629
|
+
return new Promise((resolve, reject)=>{
|
|
630
|
+
const command = 'npm';
|
|
631
|
+
const args = [
|
|
632
|
+
'audit',
|
|
633
|
+
'--json'
|
|
634
|
+
];
|
|
635
|
+
const child = spawn(command, args, {
|
|
636
|
+
cwd: scan.target.path,
|
|
637
|
+
stdio: [
|
|
638
|
+
'pipe',
|
|
639
|
+
'pipe',
|
|
640
|
+
'pipe'
|
|
641
|
+
]
|
|
642
|
+
});
|
|
643
|
+
let stdout = '';
|
|
644
|
+
let stderr = '';
|
|
645
|
+
child.stdout?.on('data', (data)=>{
|
|
646
|
+
stdout += data.toString();
|
|
647
|
+
});
|
|
648
|
+
child.stderr?.on('data', (data)=>{
|
|
649
|
+
stderr += data.toString();
|
|
650
|
+
});
|
|
651
|
+
child.on('close', (code)=>{
|
|
652
|
+
try {
|
|
653
|
+
const auditResult = JSON.parse(stdout);
|
|
654
|
+
const findings = this.parseNpmAuditResults(auditResult);
|
|
655
|
+
resolve(findings);
|
|
656
|
+
} catch (error) {
|
|
657
|
+
reject(new Error(`Failed to parse npm audit results: ${error instanceof Error ? error.message : String(error)}`));
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
child.on('error', (error)=>{
|
|
661
|
+
reject(error);
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
async executeGitleaksScan(scan) {
|
|
666
|
+
// Mock Gitleaks scan for secrets detection
|
|
667
|
+
return [
|
|
668
|
+
{
|
|
669
|
+
id: `finding-${Date.now()}-2`,
|
|
670
|
+
title: 'Exposed AWS Access Key',
|
|
671
|
+
description: 'AWS access key found in source code',
|
|
672
|
+
severity: 'high',
|
|
673
|
+
category: 'secret',
|
|
674
|
+
location: {
|
|
675
|
+
file: 'config/aws.js',
|
|
676
|
+
line: 12,
|
|
677
|
+
column: 20
|
|
678
|
+
},
|
|
679
|
+
evidence: {
|
|
680
|
+
snippet: 'const accessKey = "AKIA123456789..."',
|
|
681
|
+
context: 'Hardcoded AWS credentials'
|
|
682
|
+
},
|
|
683
|
+
impact: 'Unauthorized access to AWS resources',
|
|
684
|
+
remediation: {
|
|
685
|
+
description: 'Remove hardcoded credentials and use environment variables or IAM roles',
|
|
686
|
+
effort: 'medium',
|
|
687
|
+
priority: 'high',
|
|
688
|
+
autoFixable: false,
|
|
689
|
+
steps: [
|
|
690
|
+
'Remove hardcoded credentials',
|
|
691
|
+
'Use environment variables',
|
|
692
|
+
'Rotate compromised keys'
|
|
693
|
+
],
|
|
694
|
+
references: [
|
|
695
|
+
'https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html'
|
|
696
|
+
]
|
|
697
|
+
},
|
|
698
|
+
status: 'open',
|
|
699
|
+
tags: [
|
|
700
|
+
'secret',
|
|
701
|
+
'aws',
|
|
702
|
+
'credentials'
|
|
703
|
+
],
|
|
704
|
+
metadata: {},
|
|
705
|
+
firstSeen: new Date(),
|
|
706
|
+
lastSeen: new Date(),
|
|
707
|
+
occurrences: 1
|
|
708
|
+
}
|
|
709
|
+
];
|
|
710
|
+
}
|
|
711
|
+
async executeCheckovScan(scan) {
|
|
712
|
+
// Mock Checkov scan for infrastructure as code
|
|
713
|
+
return [];
|
|
714
|
+
}
|
|
715
|
+
async executeGenericScan(scan) {
|
|
716
|
+
// Generic scan implementation
|
|
717
|
+
return [];
|
|
718
|
+
}
|
|
719
|
+
parseNpmAuditResults(auditResult) {
|
|
720
|
+
const findings = [];
|
|
721
|
+
if (auditResult.vulnerabilities) {
|
|
722
|
+
for (const [packageName, vulnData] of Object.entries(auditResult.vulnerabilities)){
|
|
723
|
+
const vuln = vulnData;
|
|
724
|
+
findings.push({
|
|
725
|
+
id: `finding-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
726
|
+
title: `${vuln.severity} vulnerability in ${packageName}`,
|
|
727
|
+
description: vuln.title || 'Vulnerability detected',
|
|
728
|
+
severity: vuln.severity,
|
|
729
|
+
category: 'vulnerability',
|
|
730
|
+
cve: vuln.cve,
|
|
731
|
+
location: {
|
|
732
|
+
file: 'package.json',
|
|
733
|
+
component: packageName
|
|
734
|
+
},
|
|
735
|
+
evidence: {
|
|
736
|
+
snippet: `"${packageName}": "${vuln.range}"`,
|
|
737
|
+
references: vuln.url ? [
|
|
738
|
+
vuln.url
|
|
739
|
+
] : []
|
|
740
|
+
},
|
|
741
|
+
impact: vuln.overview || 'Security vulnerability',
|
|
742
|
+
remediation: {
|
|
743
|
+
description: vuln.recommendation || 'Update to a secure version',
|
|
744
|
+
effort: 'low',
|
|
745
|
+
priority: vuln.severity === 'info' ? 'low' : vuln.severity,
|
|
746
|
+
autoFixable: true,
|
|
747
|
+
steps: [
|
|
748
|
+
`npm update ${packageName}`
|
|
749
|
+
],
|
|
750
|
+
references: vuln.url ? [
|
|
751
|
+
vuln.url
|
|
752
|
+
] : []
|
|
753
|
+
},
|
|
754
|
+
status: 'open',
|
|
755
|
+
tags: [
|
|
756
|
+
'npm',
|
|
757
|
+
'dependency'
|
|
758
|
+
],
|
|
759
|
+
metadata: {
|
|
760
|
+
packageName,
|
|
761
|
+
range: vuln.range
|
|
762
|
+
},
|
|
763
|
+
firstSeen: new Date(),
|
|
764
|
+
lastSeen: new Date(),
|
|
765
|
+
occurrences: 1
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return findings;
|
|
770
|
+
}
|
|
771
|
+
calculateScanMetrics(scan) {
|
|
772
|
+
const findings = scan.results;
|
|
773
|
+
scan.metrics.totalFindings = findings.length;
|
|
774
|
+
scan.metrics.criticalFindings = findings.filter((f)=>f.severity === 'critical').length;
|
|
775
|
+
scan.metrics.highFindings = findings.filter((f)=>f.severity === 'high').length;
|
|
776
|
+
scan.metrics.mediumFindings = findings.filter((f)=>f.severity === 'medium').length;
|
|
777
|
+
scan.metrics.lowFindings = findings.filter((f)=>f.severity === 'low').length;
|
|
778
|
+
scan.metrics.falsePositives = findings.filter((f)=>f.status === 'false-positive').length;
|
|
779
|
+
scan.metrics.suppressed = findings.filter((f)=>f.status === 'suppressed').length;
|
|
780
|
+
}
|
|
781
|
+
async runComplianceChecks(scan) {
|
|
782
|
+
// Mock compliance checks
|
|
783
|
+
const frameworks = [
|
|
784
|
+
'SOC2',
|
|
785
|
+
'GDPR',
|
|
786
|
+
'PCI-DSS'
|
|
787
|
+
];
|
|
788
|
+
for (const framework of frameworks){
|
|
789
|
+
const checks = await this.runFrameworkChecks(framework, {
|
|
790
|
+
projectId: scan.projectId
|
|
791
|
+
});
|
|
792
|
+
scan.compliance.requirements.push(...checks);
|
|
793
|
+
}
|
|
794
|
+
scan.compliance.frameworks = frameworks;
|
|
795
|
+
scan.compliance.passedChecks = scan.compliance.requirements.filter((r)=>r.status === 'passed').length;
|
|
796
|
+
scan.compliance.failedChecks = scan.compliance.requirements.filter((r)=>r.status === 'failed').length;
|
|
797
|
+
scan.compliance.overallScore = scan.compliance.requirements.length > 0 ? scan.compliance.passedChecks / scan.compliance.requirements.length * 100 : 0;
|
|
798
|
+
}
|
|
799
|
+
async runFrameworkChecks(framework, scope) {
|
|
800
|
+
// Mock compliance checks for different frameworks
|
|
801
|
+
const mockChecks = [
|
|
802
|
+
{
|
|
803
|
+
id: `check-${Date.now()}-1`,
|
|
804
|
+
framework,
|
|
805
|
+
control: 'CC6.1',
|
|
806
|
+
description: 'Encryption in transit',
|
|
807
|
+
status: 'passed',
|
|
808
|
+
severity: 'high',
|
|
809
|
+
evidence: 'TLS 1.2+ configured',
|
|
810
|
+
lastChecked: new Date()
|
|
811
|
+
},
|
|
812
|
+
{
|
|
813
|
+
id: `check-${Date.now()}-2`,
|
|
814
|
+
framework,
|
|
815
|
+
control: 'CC6.7',
|
|
816
|
+
description: 'Encryption at rest',
|
|
817
|
+
status: 'failed',
|
|
818
|
+
severity: 'medium',
|
|
819
|
+
remediation: 'Enable database encryption',
|
|
820
|
+
lastChecked: new Date()
|
|
821
|
+
}
|
|
822
|
+
];
|
|
823
|
+
return mockChecks;
|
|
824
|
+
}
|
|
825
|
+
async generateRemediationRecommendations(scan) {
|
|
826
|
+
const autoFixable = scan.results.filter((f)=>f.remediation.autoFixable);
|
|
827
|
+
const manualReview = scan.results.filter((f)=>!f.remediation.autoFixable);
|
|
828
|
+
scan.remediation.autoFixAvailable = autoFixable;
|
|
829
|
+
scan.remediation.manualReview = manualReview;
|
|
830
|
+
// Generate general recommendations
|
|
831
|
+
scan.remediation.recommendations = [
|
|
832
|
+
{
|
|
833
|
+
id: `rec-${Date.now()}-1`,
|
|
834
|
+
title: 'Implement Automated Dependency Updates',
|
|
835
|
+
description: 'Set up automated dependency updates to reduce vulnerability exposure',
|
|
836
|
+
category: 'vulnerability-management',
|
|
837
|
+
priority: 'high',
|
|
838
|
+
effort: 'medium',
|
|
839
|
+
impact: 'Reduces time to patch vulnerabilities',
|
|
840
|
+
implementation: {
|
|
841
|
+
steps: [
|
|
842
|
+
'Configure Dependabot or Renovate',
|
|
843
|
+
'Set up automated testing pipeline',
|
|
844
|
+
'Enable auto-merge for low-risk updates'
|
|
845
|
+
],
|
|
846
|
+
tools: [
|
|
847
|
+
'Dependabot',
|
|
848
|
+
'Renovate',
|
|
849
|
+
'GitHub Actions'
|
|
850
|
+
],
|
|
851
|
+
timeEstimate: '2-4 hours',
|
|
852
|
+
cost: 'Free'
|
|
853
|
+
},
|
|
854
|
+
references: [
|
|
855
|
+
'https://docs.github.com/en/code-security/dependabot',
|
|
856
|
+
'https://renovatebot.com/'
|
|
857
|
+
],
|
|
858
|
+
applicableFrameworks: [
|
|
859
|
+
'SOC2',
|
|
860
|
+
'ISO27001'
|
|
861
|
+
]
|
|
862
|
+
}
|
|
863
|
+
];
|
|
864
|
+
}
|
|
865
|
+
async checkNotificationThresholds(scan) {
|
|
866
|
+
const thresholds = scan.notifications.thresholds;
|
|
867
|
+
if (scan.metrics.criticalFindings >= thresholds.critical || scan.metrics.highFindings >= thresholds.high || scan.metrics.mediumFindings >= thresholds.medium) {
|
|
868
|
+
await this.sendScanNotification(scan);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
async sendScanNotification(scan) {
|
|
872
|
+
const message = `Security scan '${scan.name}' completed with ${scan.metrics.totalFindings} findings (${scan.metrics.criticalFindings} critical, ${scan.metrics.highFindings} high)`;
|
|
873
|
+
this.emit('notification:scan', {
|
|
874
|
+
scan,
|
|
875
|
+
message,
|
|
876
|
+
severity: scan.metrics.criticalFindings > 0 ? 'critical' : scan.metrics.highFindings > 0 ? 'high' : 'medium'
|
|
877
|
+
});
|
|
878
|
+
this.logger.warn(message);
|
|
879
|
+
}
|
|
880
|
+
async autoAssignIncident(incident) {
|
|
881
|
+
// Auto-assign based on severity and type
|
|
882
|
+
const assignmentRules = {
|
|
883
|
+
critical: [
|
|
884
|
+
'security-lead',
|
|
885
|
+
'ciso'
|
|
886
|
+
],
|
|
887
|
+
high: [
|
|
888
|
+
'security-team'
|
|
889
|
+
],
|
|
890
|
+
medium: [
|
|
891
|
+
'security-analyst'
|
|
892
|
+
],
|
|
893
|
+
low: [
|
|
894
|
+
'security-analyst'
|
|
895
|
+
]
|
|
896
|
+
};
|
|
897
|
+
incident.response.assignedTo = assignmentRules[incident.severity] || [
|
|
898
|
+
'security-team'
|
|
899
|
+
];
|
|
900
|
+
}
|
|
901
|
+
async sendIncidentNotification(incident) {
|
|
902
|
+
const message = `SECURITY INCIDENT: ${incident.title} (${incident.severity.toUpperCase()})`;
|
|
903
|
+
this.emit('notification:incident', {
|
|
904
|
+
incident,
|
|
905
|
+
message,
|
|
906
|
+
urgency: incident.severity === 'critical' ? 'immediate' : 'high'
|
|
907
|
+
});
|
|
908
|
+
this.logger.error(message);
|
|
909
|
+
}
|
|
910
|
+
updateIncidentTimeline(incident, newStatus) {
|
|
911
|
+
const now = new Date();
|
|
912
|
+
switch(newStatus){
|
|
913
|
+
case 'investigating':
|
|
914
|
+
incident.timeline.acknowledged = now;
|
|
915
|
+
break;
|
|
916
|
+
case 'contained':
|
|
917
|
+
incident.timeline.contained = now;
|
|
918
|
+
break;
|
|
919
|
+
case 'resolved':
|
|
920
|
+
incident.timeline.resolved = now;
|
|
921
|
+
break;
|
|
922
|
+
case 'closed':
|
|
923
|
+
incident.timeline.closed = now;
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
async saveScan(scan) {
|
|
928
|
+
const filePath = join(this.securityPath, 'scans', `${scan.id}.json`);
|
|
929
|
+
await writeFile(filePath, JSON.stringify(scan, null, 2));
|
|
930
|
+
}
|
|
931
|
+
async savePolicy(policy) {
|
|
932
|
+
const filePath = join(this.securityPath, 'policies', `${policy.id}.json`);
|
|
933
|
+
await writeFile(filePath, JSON.stringify(policy, null, 2));
|
|
934
|
+
}
|
|
935
|
+
async saveIncident(incident) {
|
|
936
|
+
const filePath = join(this.securityPath, 'incidents', `${incident.id}.json`);
|
|
937
|
+
await writeFile(filePath, JSON.stringify(incident, null, 2));
|
|
938
|
+
}
|
|
939
|
+
addAuditEntry(target, userId, action, targetType, details) {
|
|
940
|
+
const entry = {
|
|
941
|
+
id: `audit-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
942
|
+
timestamp: new Date(),
|
|
943
|
+
userId,
|
|
944
|
+
action,
|
|
945
|
+
target: targetType,
|
|
946
|
+
details
|
|
947
|
+
};
|
|
948
|
+
target.auditLog.push(entry);
|
|
949
|
+
}
|
|
950
|
+
groupBy(array, key) {
|
|
951
|
+
return array.reduce((groups, item)=>{
|
|
952
|
+
const value = String(item[key]);
|
|
953
|
+
groups[value] = (groups[value] || 0) + 1;
|
|
954
|
+
return groups;
|
|
955
|
+
}, {});
|
|
956
|
+
}
|
|
957
|
+
calculateMTTR(findings) {
|
|
958
|
+
const resolvedFindings = findings.filter((f)=>f.status === 'resolved' && f.firstSeen && f.lastSeen);
|
|
959
|
+
if (resolvedFindings.length === 0) return 0;
|
|
960
|
+
const totalTime = resolvedFindings.reduce((sum, f)=>sum + (f.lastSeen.getTime() - f.firstSeen.getTime()), 0);
|
|
961
|
+
return totalTime / resolvedFindings.length;
|
|
962
|
+
}
|
|
963
|
+
calculateMTTD(incidents) {
|
|
964
|
+
const detectedIncidents = incidents.filter((i)=>i.timeline.detected && i.timeline.reported);
|
|
965
|
+
if (detectedIncidents.length === 0) return 0;
|
|
966
|
+
const totalTime = detectedIncidents.reduce((sum, i)=>sum + (i.timeline.reported.getTime() - i.timeline.detected.getTime()), 0);
|
|
967
|
+
return totalTime / detectedIncidents.length;
|
|
968
|
+
}
|
|
969
|
+
calculateMTTResponse(incidents) {
|
|
970
|
+
const respondedIncidents = incidents.filter((i)=>i.timeline.reported && i.timeline.acknowledged);
|
|
971
|
+
if (respondedIncidents.length === 0) return 0;
|
|
972
|
+
const totalTime = respondedIncidents.reduce((sum, i)=>sum + (i.timeline.acknowledged.getTime() - i.timeline.reported.getTime()), 0);
|
|
973
|
+
return totalTime / respondedIncidents.length;
|
|
974
|
+
}
|
|
975
|
+
calculateIncidentMTTR(incidents) {
|
|
976
|
+
const resolvedIncidents = incidents.filter((i)=>i.timeline.reported && i.timeline.resolved);
|
|
977
|
+
if (resolvedIncidents.length === 0) return 0;
|
|
978
|
+
const totalTime = resolvedIncidents.reduce((sum, i)=>sum + (i.timeline.resolved.getTime() - i.timeline.reported.getTime()), 0);
|
|
979
|
+
return totalTime / resolvedIncidents.length;
|
|
980
|
+
}
|
|
981
|
+
constructor(securityPath = './security', logger, config){
|
|
982
|
+
super(), _define_property(this, "scans", new Map()), _define_property(this, "policies", new Map()), _define_property(this, "incidents", new Map()), _define_property(this, "vulnerabilityDatabases", new Map()), _define_property(this, "securityPath", void 0), _define_property(this, "logger", void 0), _define_property(this, "config", void 0);
|
|
983
|
+
this.securityPath = securityPath;
|
|
984
|
+
this.logger = logger || new Logger({
|
|
985
|
+
level: 'info',
|
|
986
|
+
format: 'text',
|
|
987
|
+
destination: 'console'
|
|
988
|
+
});
|
|
989
|
+
this.config = config || ConfigManager.getInstance();
|
|
990
|
+
}
|
|
991
|
+
}
|