feat(arsenal): parse scanner JSON into structured findings (#42)

The generic adapter factory returned raw stdout only (`adapter-tools.ts` success
path), so 35 catalogued scanners with `parserStatus: 'planned'` never populated the
structured `ToolResult.findings` channel — their output was dropped on the floor and
the agent could neither verify nor chain on it. The whole downstream pipe already
exists and is honest-by-construction: the agent loop stamps `provenance:'tool'` + the
raw output, the operator materialises each finding with output-evidence, and the live
gate (`evidence/gate.ts`) marks it verified.

Add `src/arsenal/parsers.ts` — `parseToolOutput(toolId, rawStdout) → ToolFinding[]`
for the five scanners that already emit machine-readable JSON via their existing arg
templates (zero template changes): nuclei (-jsonl), httpx (-json), dalfox (--format
json), ffuf (-of json), katana (-jsonl). Parsers are pure, dependency-free, and NEVER
throw: empty/garbled/unknown input yields `[]`, never a fabricated finding (same
discipline as stub-honesty / no-phantom-tools). The factory attaches parsed findings
while ALWAYS keeping the raw stdout as `output` — the evidence of record the gate checks.

- nuclei/dalfox emit CWE, which the tool channel dropped: add optional `cwe?: string[]`
  to `ToolFinding` and thread it through the operator's finding materialisation.
- flip `parserStatus: 'planned' → 'structured'` for httpx, dalfox, katana (nuclei/ffuf
  were already structured).

Adds `src/__tests__/parsers.test.ts` + fixtures: per-scanner field mapping, the
honesty contract (empty/garbled/adversarial → [], no throw), a factory-wiring check
that a minted adapter returns findings while preserving raw stdout, and an end-to-end
assertion that every parsed finding PASSES `gateLiveFinding` with provenance='tool'.

The minted-adapter path is gated behind T3MP3ST_FULL_ARSENAL, so the benchmarked
default arsenal is untouched. Supply-chain JSON tools (semgrep/gitleaks/trivy/grype)
and secret scanners (need redaction) are a clean follow-up.
This commit is contained in:
Pazificateur69 authored and GitHub committed 2026-07-15 19:43:51 -04:00
1 parent 0f3213b310
commit f8c283377c
11 files changed
+423 -4

No files matched your search

+3 -3
View File
@@ -179,7 +179,7 @@ export const TOOL_ADAPTERS: ToolAdapter[] = [
outputFormats: ['jsonl', 'text'],
installHint: 'brew install projectdiscovery/tap/httpx',
commandHint: 'httpx -u https://example.com -status-code -title -tech-detect -json',
parserStatus: 'planned',
parserStatus: 'structured',
notes: 'HTTP probing and technology detection for discovered assets.',
},
{
@@ -211,7 +211,7 @@ export const TOOL_ADAPTERS: ToolAdapter[] = [
outputFormats: ['jsonl', 'text'],
installHint: 'brew install projectdiscovery/tap/katana',
commandHint: 'katana -u https://example.com -jsonl -silent',
parserStatus: 'planned',
parserStatus: 'structured',
notes: 'Crawler for endpoint discovery and attack-surface mapping.',
},
{
@@ -307,7 +307,7 @@ export const TOOL_ADAPTERS: ToolAdapter[] = [
outputFormats: ['json', 'text'],
installHint: 'brew install dalfox',
commandHint: 'dalfox url https://example.com?q=test -o result.json --format json',
parserStatus: 'planned',
parserStatus: 'structured',
notes: 'XSS validation adapter for scoped endpoints.',
},
{