feat(arsenal): structured parsers for source / supply-chain scanners (semgrep, trivy, grype, gitleaks)#43
Conversation
…able findings 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.
Follow-up to the JSON-scanner parser layer: wire semgrep, gitleaks, trivy and
grype into parseToolOutput so their findings become structured, gate-verifiable
evidence instead of raw text (they were parserStatus:'planned').
- semgrep (scan --json) → one finding per rule match; ERROR/WARNING/INFO
mapped to severity; CWE token pulled from
metadata (e.g. "CWE-78: …" → CWE-78); refs → remediation.
- trivy (fs --format json) → one finding per package vuln; CVE + CweIDs +
"upgrade <pkg> to <fixed>" remediation.
- grype (dir:. -o json) → one finding per match; CVE + package coordinates.
- gitleaks (detect --report json --redact) → one high finding per secret. Defence in
depth: the details are run through redactString()
so a raw secret can NEVER reach a finding / the vault,
even though the adapter already passes --redact.
Broadens the severity map to cover scanner vocabularies (ERROR/WARNING, CRITICAL…
NEGLIGIBLE, moderate) onto the five canonical levels. Flips parserStatus to
'structured' for the four tools. Extends parsers.test.ts + fixtures: field mapping,
the gitleaks redaction guarantee, and the end-to-end gate pass for every new scanner.
Stacked on the parser layer (elder-plinius#42); pairs with the scanner-invocation fix (elder-plinius#40) that
gives these tools the JSON-emitting arg templates. Until elder-plinius#40 lands the parsers simply
degrade to [] (no JSON to parse) — no misbehaviour. Secret scanners beyond gitleaks
and SARIF-style tools remain a follow-up.
|
Reviewed — sound, and correctly stacked on #42 (net-new commit |
|
Please rebase this branch onto current The parser work should be reviewed on its own, but the branch currently carries stale-base deletions of benchmark corpora, benchmark scripts, provenance docs, and tests. That makes the merge unsafe. Suggested agent repair path:
|
What
Extends the structured-parser layer (#42) to the source / supply-chain scanners, so their output becomes gate-verifiable
Findings instead of raw text (they wereparserStatus: 'planned'):scan --config auto --json ."CWE-78: …"→CWE-78) · refs → remediationfs --format json .upgrade <pkg> to <fixed>remediationdir:. -o jsondetect --report-format json --redactHonesty / safety
[], never a fabricated finding. Raw stdout is always kept as the evidence of record.--redact, but the parser also routes finding details throughredactString()(src/redact.ts), so a raw secret can never reach aFindingor the evidence vault. A test pins this: an AWS key present in the raw report is[redacted]in the finding.Tests
Extends
parsers.test.ts+ fixtures: per-scanner field mapping (CVE/CWE/severity/remediation), the gitleaks redaction guarantee, and the end-to-end assertion that every new scanner's parsed finding passesgateLiveFindingwith provenance='tool'.Scope
SARIF-style output and secret scanners beyond gitleaks (trufflehog etc.) remain a clean follow-up.
Review standard (all green locally)
typecheck·test·doctor·verify-claims·test:no-fitting·test:no-self-fitting·test:gate·prompt:audit·smoke