| 438 | }); |
| 439 | |
| 440 | function parseNaabuOutput(raw: string): Finding[] { |
| 441 | if (!raw.trim()) { |
| 442 | return []; |
| 443 | } |
| 444 | |
| 445 | const findings: Finding[] = []; |
| 446 | |
| 447 | raw |
| 448 | .split(/\r?\n/) |
| 449 | .map((line) => line.trim()) |
| 450 | .filter((line) => line.length > 0) |
| 451 | .forEach((line) => { |
| 452 | let payload: any = null; |
| 453 | try { |
| 454 | payload = JSON.parse(line); |
| 455 | } catch { |
| 456 | payload = null; |
| 457 | } |
| 458 | |
| 459 | if (payload && typeof payload === 'object') { |
| 460 | const host = |
| 461 | typeof payload.host === 'string' && payload.host.length > 0 |
| 462 | ? payload.host |
| 463 | : typeof payload.ip === 'string' |
| 464 | ? payload.ip |
| 465 | : ''; |
| 466 | const portValue = Number(payload.port); |
| 467 | if (!host || !Number.isFinite(portValue)) { |
| 468 | return; |
| 469 | } |
| 470 | |
| 471 | const protocol = |
| 472 | typeof payload.proto === 'string' |
| 473 | ? payload.proto |
| 474 | : typeof payload.protocol === 'string' |
| 475 | ? payload.protocol |
| 476 | : 'tcp'; |
| 477 | |
| 478 | const finding: Finding = { |
| 479 | host, |
| 480 | ip: typeof payload.ip === 'string' && payload.ip.length > 0 ? payload.ip : null, |
| 481 | port: portValue, |
| 482 | protocol, |
| 483 | }; |
| 484 | findings.push(finding); |
| 485 | return; |
| 486 | } |
| 487 | |
| 488 | const parts = line.split(':'); |
| 489 | if (parts.length === 2) { |
| 490 | const portValue = Number(parts[1]); |
| 491 | if (Number.isFinite(portValue)) { |
| 492 | findings.push({ |
| 493 | host: parts[0], |
| 494 | ip: null, |
| 495 | port: portValue, |
| 496 | protocol: 'tcp', |
| 497 | }); |