omen-sec-cli 1.0.17 → 1.0.19

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/README.md CHANGED
@@ -1,78 +1,84 @@
1
- # <p align="center"> <img src="https://img.icons8.com/nolan/128/security-shield.png" width="100" /> <br> OMEN SEC-CLI </p>
1
+ # <p align="center"> <img src="https://img.icons8.com/nolan/128/security-shield.png" width="100" /> <br> OMEN SEC-CLI v1.0.19 </p>
2
2
 
3
3
  <p align="center">
4
- <img src="https://img.shields.io/badge/Version-1.0.6-red?style=for-the-badge" />
5
- <img src="https://img.shields.io/badge/AI--Powered-DevSecOps-000000?style=for-the-badge&logo=openai" />
6
- <img src="https://img.shields.io/badge/License-MIT-green?style=for-the-badge" />
4
+ <img src="https://img.shields.io/badge/Version-1.0.19-red?style=for-the-badge" />
5
+ <img src="https://img.shields.io/badge/Phase--Based-DevSecOps-000000?style=for-the-badge&logo=openai" />
6
+ <img src="https://img.shields.io/badge/Zero--Copy-AI--Protocol-green?style=for-the-badge" />
7
7
  </p>
8
8
 
9
9
  ---
10
10
 
11
- ## 💀 O que é o OMEN?
11
+ ## 🛡️ O que é o OMEN?
12
12
 
13
- O **OMEN SEC-CLI** não é apenas um script de segurança; é um **Framework de Auditoria DevSecOps** projetado para elevar o nível de proteção das suas aplicações. Ele transforma sua IA local (Trae, Cursor, Copilot) em um **Arquiteto de Segurança de Elite**, capaz de auditar, detectar e corrigir vulnerabilidades em tempo real.
13
+ O **OMEN SEC-CLI** evoluiu de um simples scanner para um **Framework de Auditoria DevSecOps Profissional**. Inspirado no modelo operacional de ferramentas de elite, o OMEN automatiza o ciclo completo de segurança: desde a descoberta da stack até a verificação das correções.
14
14
 
15
- Diferente de outras ferramentas, o OMEN utiliza o conceito de **Zero-Copy AI Handover**, onde a CLI "sequestra" o contexto da sua IA de desenvolvimento para realizar correções automáticas (Auto-Fix) baseadas em protocolos militares de segurança.
15
+ Ele é o coração do seu fluxo de trabalho de segurança, permitindo que IAs locais (como o **Trae** ou **Cursor**) ajam como auditores e arquitetos de segurança, executando correções diretamente no código através do protocolo **Zero-Copy AI Handover**.
16
16
 
17
17
  ---
18
18
 
19
- ## ⚡ Funcionalidades Principais
19
+ ## ⚡ Workflow por Fases (Inspirado em get-shit-done-cc)
20
20
 
21
- ### 1. 🧠 AI Zero-Copy (Auto-Fix)
22
- Integração nativa com IAs locais. Ao rodar com a flag `--auto-fix`, o OMEN emite um protocolo de **Dual Personality (Auditor & Arquiteto)** que força sua IA a assumir o controle e corrigir o código sem que você precise copiar uma única linha.
21
+ O OMEN 2.0 agora opera em um ciclo stateful de 5 fases:
23
22
 
24
- ### 2. 🌐 Scan Remoto Inteligente (Spider & Fuzzer)
25
- Não olhamos apenas a superfície. Nosso scanner remoto possui:
26
- - **Spider/Crawler:** Mapeia todos os links internos para encontrar vulnerabilidades escondidas.
27
- - **Fuzzer de Caminhos:** Tenta localizar arquivos sensíveis (`.env`, `.git`, `/admin`, `/config`).
28
- - **Injection Tester:** Testes automatizados de XSS Refletido e SQL Injection.
29
-
30
- ### 3. 🔍 Scan Local Profundo & CVEs Reais
31
- - **Integração OSV.dev (Google):** Consulta em tempo real o banco de dados de vulnerabilidades para suas dependências no `package.json`.
32
- - **SAST (Static Application Security Testing):** Detecta segredos hardcoded, uso de `eval()`, injeções de SQL e padrões inseguros no código fonte.
33
-
34
- ### 4. 🛠️ Sistema de Plugins (Regras Customizadas)
35
- Crie suas próprias regras de segurança em um arquivo `omen-rules.yaml` na raiz do seu projeto. Defina padrões Regex, severidade e alertas personalizados que o OMEN deve seguir.
36
-
37
- ### 5. 📊 Dashboard Local (Cyberpunk Web UI)
38
- Visualize seus relatórios de forma profissional. O OMEN sobe um servidor local com uma interface moderna para análise detalhada de scores e riscos.
23
+ 1. **🔍 Discover**: Detecta automaticamente a stack (Node, React, Python, PHP), entrypoints e estratégia de boot.
24
+ 2. **📋 Plan**: Gera um plano de execução personalizado baseado na estrutura do seu projeto.
25
+ 3. **🚀 Execute**: Orquestra analisadores estáticos (SAST) e dinâmicos (DAST), incluindo o boot automático da aplicação local com healthchecks.
26
+ 4. **📊 Report**: Gera relatórios multi-formato, incluindo o novo **Fix Plan** (checklist de remediação).
27
+ 5. **✅ Verify**: Re-escaneia o projeto e compara os resultados para confirmar se as falhas foram resolvidas.
39
28
 
40
29
  ---
41
30
 
42
31
  ## 🚀 Instalação e Uso
43
32
 
44
- Você pode instalar o OMEN globalmente ou rodar direto via `npx`:
33
+ O OMEN deve ser usado via `npx` para garantir que você sempre tenha a versão mais recente e estável:
45
34
 
46
- ### Instalação Global
35
+ ### Fluxo Completo de Auditoria
47
36
  ```bash
48
- npm install -g omen-sec-cli
49
- ```
37
+ # 1. Descobrir a estrutura do projeto
38
+ npx omen-sec-cli discover
50
39
 
51
- ### Scan Remoto
52
- ```bash
53
- npx omen-sec-cli robotscan https://seu-alvo.com
54
- ```
40
+ # 2. Planejar o scan
41
+ npx omen-sec-cli plan
55
42
 
56
- ### Scan Local (Projeto Atual)
57
- ```bash
58
- npx omen-sec-cli robotscan --local
59
- ```
43
+ # 3. Executar o scan (SAST + DAST com Boot Local)
44
+ npx omen-sec-cli execute
60
45
 
61
- ### Modo de Auto-Correção com IA (Recomendado no Trae/Cursor)
62
- ```bash
63
- npx omen-sec-cli robotscan --local --auto-fix
46
+ # 4. Gerar relatórios e Fix Plan
47
+ npx omen-sec-cli report
48
+
49
+ # 5. Verificar correções (pós-fix)
50
+ npx omen-sec-cli verify
64
51
  ```
65
52
 
66
- ### Abrir Dashboard Web
53
+ ### Dashboard Cyberpunk
54
+ Visualize tudo em uma interface moderna e detalhada:
67
55
  ```bash
68
56
  npx omen-sec-cli ui
69
57
  ```
70
58
 
71
59
  ---
72
60
 
73
- ## ⚙️ Configuração de Regras Customizadas
61
+ ## 🧠 Zero-Copy AI (Protocolo OMEN PRIME)
62
+
63
+ O OMEN foi desenhado para ser "assimilado" por IAs. Ao abrir o arquivo `omen-reports/omen-fix-plan.md` ou `omen-ai.txt` no seu editor (Trae/Cursor), a IA assume o protocolo **Dual Personality**:
64
+ - **O AUDITOR:** Analisa a causa raiz da falha caractere por caractere.
65
+ - **O ARQUITETO:** Implementa a correção sugerida diretamente no seu código.
66
+
67
+ ---
68
+
69
+ ## 🔍 Funcionalidades de Elite
70
+
71
+ - **SAST Profundo**: Detecção de segredos, eval(), LFI, Insecure JWT, Prototype Pollution e mais.
72
+ - **DAST Inteligente**: Crawler/Spider, Path Fuzzer (com validação de falso positivo), CORS e Cookie Security.
73
+ - **Integração OSV.dev**: Consulta em tempo real de CVEs para dependências NPM.
74
+ - **Boot Local Automático**: O OMEN sobe sua aplicação, aguarda o healthcheck e executa o scan dinâmico sem intervenção manual.
75
+ - **Security Score Weighted**: Pontuação de 0 a 100 baseada na severidade e confiança das vulnerabilidades.
76
+
77
+ ---
74
78
 
75
- Crie um arquivo `omen-rules.yaml` para estender o poder do OMEN:
79
+ ## ⚙️ Configuração (omen-rules.yaml)
80
+
81
+ Estenda o scanner com suas próprias regras de segurança:
76
82
 
77
83
  ```yaml
78
84
  rules:
@@ -81,37 +87,24 @@ rules:
81
87
  severity: "Critical"
82
88
  description: "Palavra proibida detectada no código!"
83
89
  cwe: "CWE-798"
84
- - pattern: "localStorage\\.set"
85
- type: "Insecure Storage"
86
- severity: "Medium"
87
- description: "Evite salvar dados sensíveis no localStorage."
88
90
  ```
89
91
 
90
92
  ---
91
93
 
92
- ## 📂 Estrutura de Relatórios
93
-
94
- Após cada scan, o OMEN gera uma pasta `omen-reports/` com:
95
- - `omen-report.json`: Dados brutos para integração.
96
- - `omen-report.txt`: Resumo legível para humanos.
97
- - `omen-ai.txt`: Super Prompt pronto para qualquer IA externa.
98
-
99
- ---
100
-
101
- ## 🛡️ Protocolo OMEN PRIME
94
+ ## 📂 Estrutura de Relatórios (`omen-reports/`)
102
95
 
103
- Quando o OMEN detecta uma IA ativa, ele ativa o protocolo **OMEN PRIME**, dividindo a inteligência em:
104
- 1. **O AUDITOR:** Analisa falhas caractere por caractere.
105
- 2. **O ARQUITETO:** Implementa correções prontas para produção.
96
+ - `omen-report.json`: Estado completo do scan (Schema 1.0).
97
+ - `omen-fix-plan.md`: **Checklist prioritário** para remediação com guias de "How to Fix".
98
+ - `omen-report.md`: Relatório executivo para stakeholders.
99
+ - `omen-ai.txt`: Super-protocolo para handover de IA.
106
100
 
107
101
  ---
108
102
 
109
103
  ## 🤝 Comunidade e Suporte
110
104
 
111
- - **Donate**: [GitHub Sponsors](https://github.com/sponsors/omen)
105
+ - **GitHub**: [Report a Bug](https://github.com/omen-sec/omen-cli)
112
106
  - **Discord**: [Join our Community](https://discord.gg/omen-security)
113
- - **GitHub**: [Report a Bug](https://github.com/omen)
114
107
 
115
108
  <p align="center">
116
- <i>Desenvolvido para desenvolvedores que levam a segurança a sério.</i>
109
+ <i>OMEN: Security for developers, by developers.</i>
117
110
  </p>
package/bin/index.js CHANGED
@@ -1,36 +1,78 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { Command } from 'commander';
3
4
  import { runScan } from '../core/engine.js';
4
- import { showBanner, showHelp } from '../ui/banner.js';
5
- import { parseArgs } from '../utils/args.js';
5
+ import { discover, plan, execute, report, verify } from '../core/engine-v2.js';
6
+ import { showBanner } from '../ui/banner.js';
6
7
  import { startUIServer } from '../core/ui-server.js';
8
+ import { parseArgs } from '../utils/args.js';
7
9
 
8
- async function main() {
9
- const args = parseArgs(process.argv);
10
+ const program = new Command();
10
11
 
11
- if (args.flags.help) {
12
+ program
13
+ .name('omen')
14
+ .description('OMEN — AI Security Engine & DevSecOps Audit Framework')
15
+ .version('1.0.19');
16
+
17
+ // Old command for backward compatibility
18
+ program
19
+ .command('robotscan [target]')
20
+ .description('Run full automated scan (Legacy)')
21
+ .option('--local', 'Scan local project')
22
+ .option('--auto-fix', 'AI Auto-fix')
23
+ .action(async (target, options) => {
12
24
  showBanner();
13
- showHelp();
14
- return;
15
- }
25
+ const args = { command: 'robotscan', target, flags: options };
26
+ await runScan(args);
27
+ });
16
28
 
17
- if (args.flags.version) {
18
- console.log('1.0.17');
19
- return;
20
- }
29
+ // New Phase-based commands
30
+ program
31
+ .command('discover [path]')
32
+ .description('Phase 1: Detect stack, entrypoints and structure')
33
+ .action(async (path) => {
34
+ showBanner();
35
+ await discover(path || process.cwd());
36
+ });
21
37
 
22
- showBanner();
38
+ program
39
+ .command('plan')
40
+ .description('Phase 2: Generate execution plan based on discovery')
41
+ .action(async () => {
42
+ showBanner();
43
+ await plan();
44
+ });
23
45
 
24
- if (args.command === 'robotscan') {
25
- await runScan(args);
26
- } else if (args.command === 'ui') {
46
+ program
47
+ .command('execute')
48
+ .description('Phase 3: Run static and dynamic analyzers')
49
+ .action(async () => {
50
+ showBanner();
51
+ await execute();
52
+ });
53
+
54
+ program
55
+ .command('report')
56
+ .description('Phase 4: Generate audit reports')
57
+ .action(async () => {
58
+ showBanner();
59
+ await report();
60
+ });
61
+
62
+ program
63
+ .command('verify')
64
+ .description('Phase 5: Confirm if issues were resolved')
65
+ .action(async () => {
66
+ showBanner();
67
+ await verify();
68
+ });
69
+
70
+ program
71
+ .command('ui')
72
+ .description('Start local Web Dashboard')
73
+ .action(async () => {
74
+ showBanner();
27
75
  await startUIServer();
28
- } else {
29
- console.log('Use --help to see commands');
30
- }
31
- }
32
-
33
- main().catch(err => {
34
- console.error('\n[Error]', err.message);
35
- process.exit(1);
36
- });
76
+ });
77
+
78
+ program.parse(process.argv);
@@ -0,0 +1,67 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { glob } from 'glob';
4
+
5
+ export async function runDiscovery(projectPath = process.cwd()) {
6
+ const discovery = {
7
+ path: projectPath,
8
+ stack: 'Unknown',
9
+ entrypoints: [],
10
+ boot_strategy: null,
11
+ critical_files: [],
12
+ dependencies: {}
13
+ };
14
+
15
+ // 1. Load package.json if exists
16
+ try {
17
+ const pkgPath = path.join(projectPath, 'package.json');
18
+ const pkgData = JSON.parse(await fs.readFile(pkgPath, 'utf-8'));
19
+ discovery.dependencies = { ...pkgData.dependencies, ...pkgData.devDependencies };
20
+
21
+ if (discovery.dependencies['next']) discovery.stack = 'Next.js';
22
+ else if (discovery.dependencies['express']) discovery.stack = 'Node/Express';
23
+ else if (discovery.dependencies['react']) discovery.stack = 'React SPA';
24
+
25
+ // Boot strategy for Node
26
+ if (pkgData.scripts) {
27
+ if (pkgData.scripts.dev) discovery.boot_strategy = 'npm run dev';
28
+ else if (pkgData.scripts.start) discovery.boot_strategy = 'npm start';
29
+ }
30
+ } catch (e) {}
31
+
32
+ // 2. Detect Python
33
+ try {
34
+ const requirementsPath = path.join(projectPath, 'requirements.txt');
35
+ await fs.access(requirementsPath);
36
+ discovery.stack = discovery.stack === 'Unknown' ? 'Python' : discovery.stack;
37
+ discovery.critical_files.push('requirements.txt');
38
+ } catch (e) {}
39
+
40
+ // 3. Detect PHP/Laravel/Wordpress
41
+ try {
42
+ const composerPath = path.join(projectPath, 'composer.json');
43
+ await fs.access(composerPath);
44
+ discovery.stack = 'PHP/Laravel';
45
+ discovery.critical_files.push('composer.json');
46
+ } catch (e) {}
47
+
48
+ // 4. Find entrypoints
49
+ const commonEntrypoints = ['server.js', 'app.js', 'index.js', 'src/index.js', 'main.py', 'app.py'];
50
+ for (const entry of commonEntrypoints) {
51
+ try {
52
+ await fs.access(path.join(projectPath, entry));
53
+ discovery.entrypoints.push(entry);
54
+ } catch (e) {}
55
+ }
56
+
57
+ // 5. Critical Security Files
58
+ const securityFiles = ['.env', '.env.local', '.env.production', '.git/config', 'docker-compose.yml', 'Dockerfile'];
59
+ for (const file of securityFiles) {
60
+ try {
61
+ await fs.access(path.join(projectPath, file));
62
+ discovery.critical_files.push(file);
63
+ } catch (e) {}
64
+ }
65
+
66
+ return discovery;
67
+ }
@@ -0,0 +1,170 @@
1
+ import chalk from 'chalk';
2
+ import { runDiscovery } from './discover/stack-detector.js';
3
+ import { saveState, loadState } from './state/state-manager.js';
4
+ import { bootLocalApp } from './runners/local-app-runner.js';
5
+ import { scanLocalProject } from './local-scanner.js';
6
+ import { scanRemoteTarget } from './remote-scanner.js';
7
+ import { generateOutputs } from './generator.js';
8
+ import { compareWithPreviousScan } from './diff-engine.js';
9
+
10
+ export async function discover(path) {
11
+ console.log(chalk.bold.cyan('\n--- Phase 1: Discovery ---'));
12
+ const discoveryData = await runDiscovery(path);
13
+ console.log(chalk.white(`Stack detected: ${discoveryData.stack}`));
14
+ console.log(chalk.white(`Entrypoints: ${discoveryData.entrypoints.join(', ') || 'None'}`));
15
+ console.log(chalk.white(`Critical files: ${discoveryData.critical_files.join(', ')}`));
16
+
17
+ await saveState({ discovery: discoveryData });
18
+ return discoveryData;
19
+ }
20
+
21
+ export async function plan() {
22
+ console.log(chalk.bold.cyan('\n--- Phase 2: Planning ---'));
23
+ const state = await loadState();
24
+ const discovery = state.discovery;
25
+
26
+ if (!discovery || !discovery.stack) {
27
+ console.log(chalk.red('No discovery data found. Run "omen discover" first.'));
28
+ return;
29
+ }
30
+
31
+ const plan = {
32
+ steps: [
33
+ { id: 'static', action: 'Static Analysis', status: 'pending' },
34
+ { id: 'dependencies', action: 'Dependency Audit', status: 'pending' }
35
+ ]
36
+ };
37
+
38
+ if (discovery.boot_strategy) {
39
+ plan.steps.push({ id: 'boot', action: `Boot App (${discovery.boot_strategy})`, status: 'pending' });
40
+ plan.steps.push({ id: 'dynamic', action: 'Dynamic Analysis (Localhost)', status: 'pending' });
41
+ }
42
+
43
+ console.log(chalk.white(`Plan generated with ${plan.steps.length} steps.`));
44
+ await saveState({ plan });
45
+ return plan;
46
+ }
47
+
48
+ export async function execute() {
49
+ console.log(chalk.bold.cyan('\n--- Phase 3: Execution ---'));
50
+ const state = await loadState();
51
+ if (!state.plan || !state.plan.steps) {
52
+ console.log(chalk.red('No plan found. Run "omen plan" first.'));
53
+ return;
54
+ }
55
+
56
+ let vulnerabilities = [];
57
+ let executionLogs = [];
58
+
59
+ for (const step of state.plan.steps) {
60
+ console.log(chalk.yellow(`\nExecuting: ${step.action}...`));
61
+
62
+ if (step.id === 'static') {
63
+ const localResult = await scanLocalProject();
64
+ vulnerabilities.push(...localResult.vulnerabilities);
65
+ executionLogs.push(`Static analysis scanned ${localResult.localFilesScanned} files.`);
66
+ }
67
+
68
+ if (step.id === 'boot') {
69
+ const bootResult = await bootLocalApp(state.discovery.boot_strategy);
70
+ if (!bootResult.success) {
71
+ vulnerabilities.push({
72
+ id: 'OMEN-OPERATIONAL-BOOT-FAIL',
73
+ kind: 'operational',
74
+ category: 'confirmed',
75
+ severity: 'high',
76
+ confidence: 'high',
77
+ title: 'App Boot Failure',
78
+ description: `The application failed to start using ${state.discovery.boot_strategy}.`,
79
+ evidence: { logs: bootResult.logs, error: bootResult.error },
80
+ remediation: 'Check application logs and environment variables.'
81
+ });
82
+ } else {
83
+ // Run dynamic analysis if boot succeeded
84
+ const dynamicResult = await scanRemoteTarget(`http://localhost:${bootResult.port}`);
85
+ vulnerabilities.push(...dynamicResult.vulnerabilities);
86
+ if (bootResult.subprocess) bootResult.subprocess.kill(); // Kill after scan
87
+ }
88
+ }
89
+ }
90
+
91
+ // Update state with execution results
92
+ const execution = {
93
+ status: 'completed',
94
+ vulnerabilities,
95
+ logs: executionLogs,
96
+ timestamp: new Date().toISOString()
97
+ };
98
+
99
+ // Calculate score
100
+ const baseScore = 100;
101
+ // Penalty based on severity
102
+ const penalties = { critical: 20, high: 10, medium: 5, low: 2, info: 0 };
103
+ const totalPenalty = vulnerabilities.reduce((acc, v) => acc + (penalties[v.severity] || 0), 0);
104
+ const score = Math.max(0, baseScore - totalPenalty);
105
+
106
+ const resultData = {
107
+ execution,
108
+ score,
109
+ vulnerabilities,
110
+ riskLevel: score < 40 ? 'Critical' : score < 70 ? 'High' : score < 90 ? 'Medium' : 'Low',
111
+ timestamp: new Date().toISOString(),
112
+ target: state.discovery?.path || process.cwd(),
113
+ scan_id: `OMEN-${Date.now()}`
114
+ };
115
+
116
+ await saveState(resultData);
117
+ console.log(chalk.green('\n[✔] Execution finished. Found', vulnerabilities.length, 'issues.'));
118
+ console.log(chalk.bold(`Security Score: ${score}/100 (${resultData.riskLevel})`));
119
+ }
120
+
121
+ export async function report() {
122
+ console.log(chalk.bold.cyan('\n--- Phase 4: Reporting ---'));
123
+ const state = await loadState();
124
+ await generateOutputs(state);
125
+ console.log(chalk.green('[✔] Reports generated in /omen-reports/'));
126
+ }
127
+
128
+ export async function verify() {
129
+ console.log(chalk.bold.cyan('\n--- Phase 5: Verification ---'));
130
+ const oldState = await loadState();
131
+
132
+ // Re-run execution to get fresh results
133
+ await execute();
134
+
135
+ const diff = await compareWithPreviousScan();
136
+
137
+ if (!diff) {
138
+ console.log(chalk.yellow('Not enough history to perform a diff verification.'));
139
+ return;
140
+ }
141
+
142
+ console.log(chalk.bold('\nVerification Results:'));
143
+
144
+ if (diff.fixedVulnerabilities.length > 0) {
145
+ console.log(chalk.green(`[✔] ${diff.fixedVulnerabilities.length} Issues RESOLVED:`));
146
+ diff.fixedVulnerabilities.forEach(v => console.log(` - ${v.title || v.description}`));
147
+ } else {
148
+ console.log(chalk.red('[!] No previously found issues were resolved.'));
149
+ }
150
+
151
+ if (diff.newVulnerabilities.length > 0) {
152
+ console.log(chalk.yellow(`[+] ${diff.newVulnerabilities.length} NEW Issues found:`));
153
+ diff.newVulnerabilities.forEach(v => console.log(` - ${v.title || v.description}`));
154
+ }
155
+
156
+ if (diff.scoreDiff !== 0) {
157
+ const color = diff.scoreDiff > 0 ? chalk.green : chalk.red;
158
+ const sign = diff.scoreDiff > 0 ? '+' : '';
159
+ console.log(color(`\nSecurity Score Change: ${sign}${diff.scoreDiff} points`));
160
+ }
161
+
162
+ await saveState({
163
+ verification: {
164
+ timestamp: new Date().toISOString(),
165
+ resolved_count: diff.fixedVulnerabilities.length,
166
+ new_count: diff.newVulnerabilities.length,
167
+ score_change: diff.scoreDiff
168
+ }
169
+ });
170
+ }
package/core/generator.js CHANGED
@@ -2,52 +2,47 @@ import fs from 'fs/promises';
2
2
  import chalk from 'chalk';
3
3
  import path from 'path';
4
4
  import { getMassiveAIProtocol } from './ai-protocol.js';
5
+ import { generateMarkdownReport } from './reporters/markdown-reporter.js';
6
+ import { generateFixPlan } from './reporters/fix-plan-reporter.js';
5
7
 
6
8
  export async function generateOutputs(scanData) {
7
- const cwd = process.cwd();
8
- const outputDir = path.join(cwd, 'omen-reports');
9
- const historyDir = path.join(cwd, '.omen', 'history');
9
+ const outputDir = path.join(process.cwd(), 'omen-reports');
10
+ const historyDir = path.join(process.cwd(), '.omen', 'history');
10
11
 
11
12
  // Criar as pastas se não existirem
12
13
  try {
13
14
  await fs.mkdir(outputDir, { recursive: true });
14
15
  await fs.mkdir(historyDir, { recursive: true });
15
- } catch (err) {
16
- console.error(chalk.red(`Failed to create output directories: ${err.message}`));
17
- return;
18
- }
16
+ } catch (err) {}
19
17
 
20
18
  const jsonContent = JSON.stringify(scanData, null, 2);
21
19
 
22
- // Simple Schema Validation
23
- if (!scanData.schema_version || !scanData.scan_id || !Array.isArray(scanData.vulnerabilities)) {
24
- console.error(chalk.red('\n[Error] Report data validation failed. Schema 1.0 requirements not met.'));
25
- }
26
-
27
20
  // JSON Report
28
21
  const jsonReportPath = path.join(outputDir, 'omen-report.json');
29
22
  await fs.writeFile(jsonReportPath, jsonContent);
23
+ console.log(chalk.cyan(`\n[Generator] Outputs saved in:`));
30
24
  console.log(` /omen-reports/omen-report.json`);
31
25
 
32
26
  // TXT Report
33
27
  const txtReportPath = path.join(outputDir, 'omen-report.txt');
34
28
  let txtContent = `OMEN SECURITY REPORT\n`;
35
29
  txtContent += `====================\n`;
36
- txtContent += `Target: ${scanData.target}\n`;
37
- txtContent += `Scan ID: ${scanData.scan_id}\n`;
38
- txtContent += `Date: ${scanData.timestamp}\n`;
39
- txtContent += `Score: ${scanData.score}/100\n`;
40
- txtContent += `Risk Level: ${scanData.riskLevel}\n\n`;
30
+ txtContent += `Target: ${scanData.target || 'Local Project'}\n`;
31
+ txtContent += `Scan ID: ${scanData.scan_id || 'N/A'}\n`;
32
+ txtContent += `Date: ${scanData.timestamp || new Date().toISOString()}\n`;
33
+ txtContent += `Score: ${scanData.score || 0}/100\n`;
34
+ txtContent += `Risk Level: ${scanData.riskLevel || 'Unknown'}\n\n`;
41
35
 
42
36
  txtContent += `VULNERABILITIES FOUND:\n`;
43
37
  txtContent += `----------------------\n`;
44
38
 
45
- if (scanData.vulnerabilities.length === 0) {
39
+ const vulnerabilities = scanData.vulnerabilities || [];
40
+ if (vulnerabilities.length === 0) {
46
41
  txtContent += `No vulnerabilities detected.\n`;
47
42
  } else {
48
- scanData.vulnerabilities.forEach(v => {
49
- txtContent += `[${v.severity.toUpperCase()}] ${v.title || v.description}\n`;
50
- txtContent += `Category: ${v.category} | Confidence: ${v.confidence}\n`;
43
+ vulnerabilities.forEach(v => {
44
+ txtContent += `[${v.severity?.toUpperCase() || 'INFO'}] ${v.title || v.description}\n`;
45
+ txtContent += `Category: ${v.category || 'N/A'} | Confidence: ${v.confidence || 'medium'}\n`;
51
46
  txtContent += `Description: ${v.description}\n`;
52
47
  if (v.remediation) txtContent += `Remediation: ${v.remediation}\n`;
53
48
  txtContent += `----------------------\n`;
@@ -55,6 +50,18 @@ export async function generateOutputs(scanData) {
55
50
  }
56
51
  await fs.writeFile(txtReportPath, txtContent);
57
52
  console.log(` /omen-reports/omen-report.txt`);
53
+
54
+ // Markdown Report
55
+ const mdReportPath = path.join(outputDir, 'omen-report.md');
56
+ const mdContent = generateMarkdownReport(scanData);
57
+ await fs.writeFile(mdReportPath, mdContent);
58
+ console.log(` /omen-reports/omen-report.md`);
59
+
60
+ // Fix Plan
61
+ const fixPlanPath = path.join(outputDir, 'omen-fix-plan.md');
62
+ const fixPlanContent = generateFixPlan(scanData);
63
+ await fs.writeFile(fixPlanPath, fixPlanContent);
64
+ console.log(` /omen-reports/omen-fix-plan.md`);
58
65
 
59
66
  // AI Protocol
60
67
  const aiReportPath = path.join(outputDir, 'omen-ai.txt');
@@ -63,6 +70,5 @@ export async function generateOutputs(scanData) {
63
70
 
64
71
  // Save historical report
65
72
  const timestamp = new Date().toISOString().replace(/:/g, '-');
66
- const historyReportPath = path.join(historyDir, `omen-report-${timestamp}.json`);
67
- await fs.writeFile(historyReportPath, jsonContent);
73
+ await fs.writeFile(path.join(historyDir, `report-${timestamp}.json`), jsonContent);
68
74
  }