(raw: string)
| 447 | }); |
| 448 | |
| 449 | function parseHttpxOutput(raw: string): Finding[] { |
| 450 | if (!raw || raw.trim().length === 0) { |
| 451 | return []; |
| 452 | } |
| 453 | |
| 454 | const lines = raw |
| 455 | .split(/\r?\n/) |
| 456 | .map((line) => line.trim()) |
| 457 | .filter((line) => line.length > 0); |
| 458 | |
| 459 | const findings: Finding[] = []; |
| 460 | |
| 461 | for (const line of lines) { |
| 462 | let payload: any = null; |
| 463 | try { |
| 464 | payload = JSON.parse(line); |
| 465 | } catch { |
| 466 | payload = null; |
| 467 | } |
| 468 | |
| 469 | if (!payload || typeof payload !== 'object') { |
| 470 | continue; |
| 471 | } |
| 472 | |
| 473 | const urlValue = (() => { |
| 474 | if (typeof payload.url === 'string' && payload.url.length > 0) { |
| 475 | return payload.url; |
| 476 | } |
| 477 | if (typeof payload['final-url'] === 'string' && payload['final-url'].length > 0) { |
| 478 | return payload['final-url']; |
| 479 | } |
| 480 | if (typeof payload.final_url === 'string' && payload.final_url.length > 0) { |
| 481 | return payload.final_url; |
| 482 | } |
| 483 | if (typeof payload.input === 'string' && payload.input.length > 0) { |
| 484 | return payload.input; |
| 485 | } |
| 486 | if (typeof payload.host === 'string' && payload.host.length > 0) { |
| 487 | return payload.host; |
| 488 | } |
| 489 | return null; |
| 490 | })(); |
| 491 | |
| 492 | if (!urlValue) { |
| 493 | continue; |
| 494 | } |
| 495 | |
| 496 | const technologies = Array.isArray(payload.tech) |
| 497 | ? payload.tech.filter( |
| 498 | (item: unknown): item is string => typeof item === 'string' && item.length > 0, |
| 499 | ) |
| 500 | : []; |
| 501 | |
| 502 | const chainStatus = Array.isArray(payload['chain-status']) |
| 503 | ? payload['chain-status'] |
| 504 | .map((value: unknown) => { |
| 505 | if (typeof value === 'number' && Number.isFinite(value)) { |
| 506 | return value; |
no test coverage detected