omen-sec-cli 1.0.20 → 1.0.21

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,7 +1,7 @@
1
- # <p align="center"> <img src="https://img.icons8.com/nolan/128/security-shield.png" width="100" /> <br> OMEN SEC-CLI v1.0.20 </p>
1
+ # <p align="center"> <img src="https://img.icons8.com/nolan/128/security-shield.png" width="100" /> <br> OMEN SEC-CLI v1.0.21 </p>
2
2
 
3
3
  <p align="center">
4
- <img src="https://img.shields.io/badge/Version-1.0.20-red?style=for-the-badge" />
4
+ <img src="https://img.shields.io/badge/Version-1.0.21-red?style=for-the-badge" />
5
5
  <img src="https://img.shields.io/badge/Phase--Based-DevSecOps-000000?style=for-the-badge&logo=openai" />
6
6
  <img src="https://img.shields.io/badge/Zero--Copy-AI--Protocol-green?style=for-the-badge" />
7
7
  </p>
package/bin/index.js CHANGED
@@ -12,7 +12,7 @@ const program = new Command();
12
12
  program
13
13
  .name('omen')
14
14
  .description('OMEN — AI Security Engine & DevSecOps Audit Framework')
15
- .version('1.0.20');
15
+ .version('1.0.21');
16
16
 
17
17
  // Old command for backward compatibility
18
18
  program
package/core/engine-v2.js CHANGED
@@ -134,7 +134,12 @@ export async function execute() {
134
134
  target: state.discovery?.path || process.cwd(),
135
135
  scan_id: `OMEN-${Date.now()}`,
136
136
  discovery: state.discovery || {},
137
- plan: state.plan || {}
137
+ plan: state.plan || {},
138
+ attack_surface: {
139
+ endpoints: state.discovery?.entrypoints || [],
140
+ tech_stack: state.discovery?.stack ? [state.discovery.stack] : [],
141
+ critical_files: state.discovery?.critical_files || []
142
+ }
138
143
  };
139
144
 
140
145
  await saveState(resultData);
@@ -15,12 +15,18 @@ export async function scanRemoteTarget(targetUrl) {
15
15
  const response = await axios.get(targetUrl, {
16
16
  timeout: 15000,
17
17
  validateStatus: () => true,
18
- headers: { 'User-Agent': 'OMEN-SEC-CLI/1.0.20 (Security Audit)' }
18
+ headers: { 'User-Agent': 'OMEN-SEC-CLI/1.0.21 (Security Audit)' }
19
19
  });
20
20
 
21
21
  serverStatus = response.status;
22
22
  const headers = response.headers;
23
- const html = response.data;
23
+ const html = response.data || '';
24
+
25
+ // --- WAF / CHALLENGE DETECTION ---
26
+ const isVercelChallenge = headers['x-vercel-mitigated'] === 'challenge' || (typeof html === 'string' && html.includes('Vercel Security Checkpoint'));
27
+ if (isVercelChallenge) {
28
+ techStack.push('Vercel WAF (Challenge Active)');
29
+ }
24
30
 
25
31
  // --- TECHNOLOGY FINGERPRINTING ---
26
32
  if (headers['x-powered-by']) techStack.push(headers['x-powered-by']);
@@ -32,98 +38,100 @@ export async function scanRemoteTarget(targetUrl) {
32
38
  if (html.includes('nuxt')) techStack.push('Nuxt.js');
33
39
 
34
40
  // --- Header Analysis (Existing - Refined Descriptions) ---
35
- if (!headers['strict-transport-security']) {
36
- headers_analysis["Strict-Transport-Security"] = "Missing";
37
- vulnerabilities.push({
38
- id: `REM-VULN-${Date.now()}-1`,
39
- kind: 'header',
40
- category: 'hardening',
41
- confidence: 'high',
42
- severity: 'medium',
43
- title: 'HSTS Header Missing',
44
- description: `HTTP Strict-Transport-Security (HSTS) header is missing. This prevents the browser from enforcing HTTPS-only connections for future visits.`,
45
- cwe: 'CWE-319',
46
- evidence: {
47
- request: { headers: { ...response.request.headers } },
48
- response: { status: response.status, headers: response.headers },
49
- reason: 'Security header "Strict-Transport-Security" not found in server response.'
50
- },
51
- remediation: 'Implement the Strict-Transport-Security header with a long max-age (e.g., 31536000) and the includeSubDomains directive.'
52
- });
53
- }
41
+ if (!isVercelChallenge) {
42
+ if (!headers['strict-transport-security']) {
43
+ headers_analysis["Strict-Transport-Security"] = "Missing";
44
+ vulnerabilities.push({
45
+ id: `REM-VULN-${Date.now()}-1`,
46
+ kind: 'header',
47
+ category: 'hardening',
48
+ confidence: 'high',
49
+ severity: 'medium',
50
+ title: 'HSTS Header Missing',
51
+ description: `HTTP Strict-Transport-Security (HSTS) header is missing. This prevents the browser from enforcing HTTPS-only connections for future visits.`,
52
+ cwe: 'CWE-319',
53
+ evidence: {
54
+ request: { headers: { ...response.request.headers } },
55
+ response: { status: response.status, headers: response.headers },
56
+ reason: 'Security header "Strict-Transport-Security" not found in server response.'
57
+ },
58
+ remediation: 'Implement the Strict-Transport-Security header with a long max-age (e.g., 31536000) and the includeSubDomains directive.'
59
+ });
60
+ }
54
61
 
55
- if (!headers['content-security-policy']) {
56
- headers_analysis["Content-Security-Policy"] = "Missing";
57
- vulnerabilities.push({
58
- id: `REM-VULN-${Date.now()}-2`,
59
- kind: 'header',
60
- category: 'confirmed',
61
- confidence: 'high',
62
- severity: 'high',
63
- title: 'Content-Security-Policy Missing',
64
- description: `CSP header is missing. Without a strict Content-Security-Policy, the application is highly vulnerable to Cross-Site Scripting (XSS) and data injection attacks.`,
65
- cwe: 'CWE-1022',
66
- evidence: {
67
- request: { headers: { ...response.request.headers } },
68
- response: { status: response.status, headers: response.headers },
69
- reason: 'Security header "Content-Security-Policy" not found in server response.'
70
- },
71
- remediation: 'Define a strict Content-Security-Policy to restrict source domains for scripts, styles, and other resources.'
72
- });
73
- } else {
74
- headers_analysis["Content-Security-Policy"] = headers['content-security-policy'];
75
- if (headers['content-security-policy'].includes("unsafe-inline")) {
62
+ if (!headers['content-security-policy']) {
63
+ headers_analysis["Content-Security-Policy"] = "Missing";
76
64
  vulnerabilities.push({
77
- id: `REM-VULN-${Date.now()}-3`,
65
+ id: `REM-VULN-${Date.now()}-2`,
78
66
  kind: 'header',
79
67
  category: 'confirmed',
80
68
  confidence: 'high',
81
69
  severity: 'high',
82
- title: 'Insecure CSP (unsafe-inline)',
83
- description: `The Content-Security-Policy allows 'unsafe-inline' for scripts or styles, significantly weakening protection against XSS.`,
84
- cwe: 'CWE-16',
85
- evidence: { finding: `policy: ${headers['content-security-policy']}` },
86
- remediation: 'Refactor the application to avoid inline scripts and styles, then remove "unsafe-inline" from the CSP.'
70
+ title: 'Content-Security-Policy Missing',
71
+ description: `CSP header is missing. Without a strict Content-Security-Policy, the application is highly vulnerable to Cross-Site Scripting (XSS) and data injection attacks.`,
72
+ cwe: 'CWE-1022',
73
+ evidence: {
74
+ request: { headers: { ...response.request.headers } },
75
+ response: { status: response.status, headers: response.headers },
76
+ reason: 'Security header "Content-Security-Policy" not found in server response.'
77
+ },
78
+ remediation: 'Define a strict Content-Security-Policy to restrict source domains for scripts, styles, and other resources.'
87
79
  });
80
+ } else {
81
+ headers_analysis["Content-Security-Policy"] = headers['content-security-policy'];
82
+ if (headers['content-security-policy'].includes("unsafe-inline")) {
83
+ vulnerabilities.push({
84
+ id: `REM-VULN-${Date.now()}-3`,
85
+ kind: 'header',
86
+ category: 'confirmed',
87
+ confidence: 'high',
88
+ severity: 'high',
89
+ title: 'Insecure CSP (unsafe-inline)',
90
+ description: `The Content-Security-Policy allows 'unsafe-inline' for scripts or styles, significantly weakening protection against XSS.`,
91
+ cwe: 'CWE-16',
92
+ evidence: { finding: `policy: ${headers['content-security-policy']}` },
93
+ remediation: 'Refactor the application to avoid inline scripts and styles, then remove "unsafe-inline" from the CSP.'
94
+ });
95
+ }
88
96
  }
89
- }
90
97
 
91
- // 3. Analisar X-Frame-Options
92
- if (!headers['x-frame-options']) {
93
- headers_analysis["X-Frame-Options"] = "Missing";
94
- vulnerabilities.push({
95
- id: `REM-VULN-${Date.now()}-4`,
96
- kind: 'header',
97
- category: 'hardening',
98
- confidence: 'high',
99
- severity: 'low',
100
- title: 'X-Frame-Options Missing',
101
- description: `Missing X-Frame-Options header. This allows the application to be embedded in an iframe on other domains, increasing Clickjacking risk.`,
102
- cwe: 'CWE-1021',
103
- evidence: {
104
- request: { headers: { ...response.request.headers } },
105
- response: { status: response.status, headers: response.headers },
106
- reason: 'Security header "X-Frame-Options" not found. This allows the site to be embedded in iframes on third-party domains.'
107
- },
108
- remediation: 'Set the X-Frame-Options header to DENY or SAMEORIGIN.'
109
- });
110
- }
98
+ // 3. Analisar X-Frame-Options
99
+ if (!headers['x-frame-options']) {
100
+ headers_analysis["X-Frame-Options"] = "Missing";
101
+ vulnerabilities.push({
102
+ id: `REM-VULN-${Date.now()}-4`,
103
+ kind: 'header',
104
+ category: 'hardening',
105
+ confidence: 'high',
106
+ severity: 'low',
107
+ title: 'X-Frame-Options Missing',
108
+ description: `Missing X-Frame-Options header. This allows the application to be embedded in an iframe on other domains, increasing Clickjacking risk.`,
109
+ cwe: 'CWE-1021',
110
+ evidence: {
111
+ request: { headers: { ...response.request.headers } },
112
+ response: { status: response.status, headers: response.headers },
113
+ reason: 'Security header "X-Frame-Options" not found. This allows the site to be embedded in iframes on third-party domains.'
114
+ },
115
+ remediation: 'Set the X-Frame-Options header to DENY or SAMEORIGIN.'
116
+ });
117
+ }
111
118
 
112
- // 3.1 Analisar X-Content-Type-Options
113
- if (!headers['x-content-type-options']) {
114
- headers_analysis["X-Content-Type-Options"] = "Missing";
115
- vulnerabilities.push({
116
- id: `REM-VULN-${Date.now()}-6`,
117
- kind: 'header',
118
- category: 'hardening',
119
- confidence: 'high',
120
- severity: 'low',
121
- title: 'X-Content-Type-Options Missing',
122
- description: `The X-Content-Type-Options: nosniff header is missing. This could allow the browser to "sniff" the content type, potentially leading to MIME-type sniffing attacks.`,
123
- cwe: 'CWE-116',
124
- evidence: { response: { headers: response.headers } },
125
- remediation: 'Add the "X-Content-Type-Options: nosniff" header to all responses.'
126
- });
119
+ // 3.1 Analisar X-Content-Type-Options
120
+ if (!headers['x-content-type-options']) {
121
+ headers_analysis["X-Content-Type-Options"] = "Missing";
122
+ vulnerabilities.push({
123
+ id: `REM-VULN-${Date.now()}-6`,
124
+ kind: 'header',
125
+ category: 'hardening',
126
+ confidence: 'high',
127
+ severity: 'low',
128
+ title: 'X-Content-Type-Options Missing',
129
+ description: `The X-Content-Type-Options: nosniff header is missing. This could allow the browser to "sniff" the content type, potentially leading to MIME-type sniffing attacks.`,
130
+ cwe: 'CWE-116',
131
+ evidence: { response: { headers: response.headers } },
132
+ remediation: 'Add the "X-Content-Type-Options: nosniff" header to all responses.'
133
+ });
134
+ }
127
135
  }
128
136
 
129
137
  // 4. Server Header Leak
@@ -297,6 +305,8 @@ export async function scanRemoteTarget(targetUrl) {
297
305
  '/api/auth/session', '/api/graphql', '/actuator/health', '/.ssh/id_rsa'
298
306
  ];
299
307
 
308
+ const forbiddenPaths = [];
309
+
300
310
  for (const path of aggressivePaths) {
301
311
  try {
302
312
  const fuzzUrl = new URL(path, targetUrl).href;
@@ -305,6 +315,11 @@ export async function scanRemoteTarget(targetUrl) {
305
315
  validateStatus: (status) => status >= 200 && status < 500
306
316
  });
307
317
 
318
+ if (fuzzRes.status === 403) {
319
+ forbiddenPaths.push(path);
320
+ continue;
321
+ }
322
+
308
323
  const finding = await validateFuzzerFinding(path, fuzzRes, fuzzUrl);
309
324
  if (finding) {
310
325
  vulnerabilities.push(finding);
@@ -314,6 +329,21 @@ export async function scanRemoteTarget(targetUrl) {
314
329
  }
315
330
  }
316
331
 
332
+ if (forbiddenPaths.length > 0) {
333
+ vulnerabilities.push({
334
+ id: `REM-ENUM-FORBIDDEN-${Date.now()}`,
335
+ kind: 'path',
336
+ category: 'informational',
337
+ confidence: 'high',
338
+ severity: 'info',
339
+ title: 'Path Enumeration: Protected Resources',
340
+ description: `Multiple paths (${forbiddenPaths.length}) returned 403 Forbidden, confirming their existence but restricted access.`,
341
+ cwe: 'CWE-204',
342
+ evidence: { forbidden_paths: forbiddenPaths },
343
+ remediation: 'Ensure that 403 responses do not leak internal structure and that access controls are correctly configured.'
344
+ });
345
+ }
346
+
317
347
  // --- OFFENSIVE PARAMETER FUZZING ---
318
348
  const injectionPayloads = [
319
349
  { type: 'SQLi', param: "' OR '1'='1", severity: 'Critical', cwe: 'CWE-89' },
@@ -338,7 +368,7 @@ export async function scanRemoteTarget(targetUrl) {
338
368
  const res = await axios.get(testUrl.href, {
339
369
  timeout: 5000,
340
370
  validateStatus: () => true,
341
- headers: { 'User-Agent': 'OMEN-SEC-CLI/1.0.20 (Security Audit)' }
371
+ headers: { 'User-Agent': 'OMEN-SEC-CLI/1.0.21 (Security Audit)' }
342
372
  });
343
373
 
344
374
  const evidence = {
@@ -41,6 +41,6 @@ export function generateFixPlan(scanData) {
41
41
  });
42
42
  }
43
43
 
44
- md += `\n*Gerado automaticamente pelo OMEN SEC-CLI v1.0.20 - Protocolo Zero-Copy AI Ativo*\n`;
44
+ md += `\n*Gerado automaticamente pelo OMEN SEC-CLI v1.0.21 - Protocolo Zero-Copy AI Ativo*\n`;
45
45
  return md;
46
46
  }
package/core/ui-server.js CHANGED
@@ -128,10 +128,10 @@ export async function startUIServer() {
128
128
  <span class="w-2 h-2 bg-blue-500 rounded-full mr-2"></span> Phase Intelligence
129
129
  </h2>
130
130
  <div class="space-y-4 text-sm">
131
- <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Stack Detected</span> <span class="text-gray-300 font-bold">${(report && report.discovery && report.discovery.stack) || 'N/A'}</span> </div>
132
- <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Boot Strategy</span> <span class="mono text-gray-300">${(report && report.discovery && report.discovery.boot_strategy) || 'None'}</span> </div>
133
- <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Execution Steps</span> <span class="text-gray-300">${(report && report.plan && report.plan.steps && report.plan.steps.length) || 0} steps</span> </div>
134
- <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Last Scan Status</span> <span class="text-green-500 font-bold uppercase">${(report && report.execution && report.execution.status) || 'N/A'}</span> </div>
131
+ <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Target URL</span> <span class="mono text-gray-300">${(report && report.target) || 'N/A'}</span> </div>
132
+ <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Tech Stack</span> <span class="text-gray-300">${(report && report.attack_surface && report.attack_surface.tech_stack && report.attack_surface.tech_stack.join(', ')) || 'N/A'}</span> </div>
133
+ <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Endpoints Discovered</span> <span class="text-gray-300">${(report && report.attack_surface && report.attack_surface.endpoints && report.attack_surface.endpoints.length) || 0}</span> </div>
134
+ <div class="flex justify-between border-b border-gray-800 pb-2"> <span class="text-gray-500">Critical Files</span> <span class="text-gray-300">${(report && report.attack_surface && report.attack_surface.critical_files && report.attack_surface.critical_files.length) || 0}</span> </div>
135
135
  </div>
136
136
  </div>
137
137
  </div>
@@ -266,7 +266,7 @@ export async function startUIServer() {
266
266
  </div>
267
267
 
268
268
  <footer class="text-center text-gray-600 mt-16 border-t border-gray-900 pt-8 mb-10">
269
- <p class="text-xs uppercase tracking-widest font-bold mb-2">OMEN Security Framework - v1.0.20</p>
269
+ <p class="text-xs uppercase tracking-widest font-bold mb-2">OMEN Security Framework - v1.0.21</p>
270
270
  <p class="text-[10px] text-gray-700 italic">"The eye that never sleeps, the code that never fails."</p>
271
271
  </footer>
272
272
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omen-sec-cli",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "OMEN — AI Security Engine",
5
5
  "engines": {
6
6
  "node": ">=20.0.0"
package/ui/banner.js CHANGED
@@ -9,7 +9,7 @@ export function showBanner() {
9
9
  ╚██████╔╝██║ ╚═╝ ██║███████╗██║ ╚████║
10
10
  `));
11
11
  console.log(chalk.cyan.bold(' OMEN — AI Security Engine '));
12
- console.log(chalk.gray(' Version: 1.0.20 \n'));
12
+ console.log(chalk.gray(' Version: 1.0.21 \n'));
13
13
  }
14
14
 
15
15
  export function showHelp() {