cipher-security 2.0.4 → 2.0.6
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/bin/cipher.js +113 -18
- package/lib/commands.js +1 -3
- package/lib/gateway/commands.js +125 -50
- package/lib/gateway/index.js +0 -2
- package/lib/mcp/server.js +241 -14
- package/lib/pipeline/index.js +3 -1
- package/lib/pipeline/osint.js +488 -239
- package/lib/pipeline/scanner.js +67 -3
- package/package.json +1 -1
package/lib/pipeline/scanner.js
CHANGED
|
@@ -361,7 +361,10 @@ class NucleiRunner {
|
|
|
361
361
|
if (effTags.length) cmd.push('-tags', effTags.join(','));
|
|
362
362
|
if (effSev.length) cmd.push('-severity', effSev.join(','));
|
|
363
363
|
cmd.push('-rl', String(sp.rateLimit), '-bs', String(sp.bulkSize));
|
|
364
|
+
if (sp.concurrency) cmd.push('-c', String(sp.concurrency));
|
|
365
|
+
if (sp.requestTimeout) cmd.push('-timeout', String(sp.requestTimeout));
|
|
364
366
|
if (sp.headless) cmd.push('-headless');
|
|
367
|
+
if (sp.extraArgs) cmd.push(...sp.extraArgs);
|
|
365
368
|
|
|
366
369
|
return this._execute(cmd, target, opts.timeout ?? DEFAULT_TIMEOUT);
|
|
367
370
|
}
|
|
@@ -374,14 +377,75 @@ class NucleiRunner {
|
|
|
374
377
|
* @param {number} [opts.timeout=600]
|
|
375
378
|
* @returns {Promise<ScanResult>}
|
|
376
379
|
*/
|
|
380
|
+
/**
|
|
381
|
+
* Run Nuclei with explicit template paths (synchronous — for quick scans).
|
|
382
|
+
* Uses execFileSync to avoid Go pipe-buffering issues with spawn.
|
|
383
|
+
* @param {string} target
|
|
384
|
+
* @param {object} opts
|
|
385
|
+
* @param {string[]} [opts.templatePaths]
|
|
386
|
+
* @param {number} [opts.timeout=30]
|
|
387
|
+
* @param {number} [opts.rateLimit=150]
|
|
388
|
+
* @param {number} [opts.concurrency=25]
|
|
389
|
+
* @param {number} [opts.requestTimeout=10]
|
|
390
|
+
* @returns {Promise<ScanResult>}
|
|
391
|
+
*/
|
|
377
392
|
scanWithTemplates(target, opts = {}) {
|
|
378
393
|
if (!this.available) return Promise.resolve(this._fail(target));
|
|
379
394
|
const bin = this._resolved || this.nucleiPath;
|
|
380
|
-
const
|
|
395
|
+
const args = ['-jsonl', '-silent', '-u', target];
|
|
381
396
|
for (const tp of opts.templatePaths ?? []) {
|
|
382
|
-
|
|
397
|
+
args.push('-t', tp);
|
|
398
|
+
}
|
|
399
|
+
args.push('-rl', String(opts.rateLimit ?? 150));
|
|
400
|
+
args.push('-c', String(opts.concurrency ?? 25));
|
|
401
|
+
args.push('-timeout', String(opts.requestTimeout ?? 10));
|
|
402
|
+
|
|
403
|
+
const start = Date.now();
|
|
404
|
+
try {
|
|
405
|
+
const out = execFileSync(bin, args, {
|
|
406
|
+
encoding: 'utf-8',
|
|
407
|
+
timeout: (opts.timeout ?? 30) * 1000,
|
|
408
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
409
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
410
|
+
});
|
|
411
|
+
const elapsed = (Date.now() - start) / 1000;
|
|
412
|
+
const findings = [];
|
|
413
|
+
for (const line of out.split('\n')) {
|
|
414
|
+
if (line.startsWith('{')) {
|
|
415
|
+
try { findings.push(Finding.fromNucleiJson(JSON.parse(line))); }
|
|
416
|
+
catch { /* skip parse errors */ }
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const sevCounts = {};
|
|
420
|
+
for (const f of findings) sevCounts[f.severity] = (sevCounts[f.severity] || 0) + 1;
|
|
421
|
+
return Promise.resolve(new ScanResult({
|
|
422
|
+
target, findings,
|
|
423
|
+
stats: { total: findings.length, ...sevCounts },
|
|
424
|
+
command: `${bin} ${args.join(' ')}`,
|
|
425
|
+
durationSeconds: Math.round(elapsed * 100) / 100,
|
|
426
|
+
success: true,
|
|
427
|
+
}));
|
|
428
|
+
} catch (err) {
|
|
429
|
+
const elapsed = (Date.now() - start) / 1000;
|
|
430
|
+
const timedOut = err.killed || err.signal === 'SIGTERM';
|
|
431
|
+
// Even on timeout, capture any partial output
|
|
432
|
+
const out = err.stdout || '';
|
|
433
|
+
const findings = [];
|
|
434
|
+
for (const line of out.split('\n')) {
|
|
435
|
+
if (line.startsWith('{')) {
|
|
436
|
+
try { findings.push(Finding.fromNucleiJson(JSON.parse(line))); }
|
|
437
|
+
catch { /* skip */ }
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return Promise.resolve(new ScanResult({
|
|
441
|
+
target, findings,
|
|
442
|
+
stats: { total: findings.length },
|
|
443
|
+
errors: timedOut ? [`Scan timed out after ${opts.timeout ?? 30}s`] : [err.message],
|
|
444
|
+
command: `${bin} ${args.join(' ')}`,
|
|
445
|
+
durationSeconds: Math.round(elapsed * 100) / 100,
|
|
446
|
+
success: !timedOut && findings.length > 0,
|
|
447
|
+
}));
|
|
383
448
|
}
|
|
384
|
-
return this._execute(cmd, target, opts.timeout ?? DEFAULT_TIMEOUT);
|
|
385
449
|
}
|
|
386
450
|
|
|
387
451
|
/**
|