Files
TigahandGitHub f570dceadc feat(report): add json findings report with -json (#313)
sarif and markdown were the only structured exports and both drop the
per-item detail the normalized finding model already holds. add a -json
flag that writes the run's findings as a json array, one object per
finding with its target, module, severity, key, title and evidence.

carry detection confidence onto the finding model too so framework
detections report their score. it rides into the json report and is
omitted for scanners that carry none. the -silent line format and the
snapshot on-disk shape stay unchanged, since the report uses a dedicated
json view rather than marshalling the finding struct directly.
2026-07-22 12:50:08 -07:00

51 lines
2.4 KiB
Go

/*
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
: :
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
: ▄█ █ █▀ · BSD 3-Clause License :
: :
: (c) 2022-2026 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
*/
package finding
import "encoding/json"
// reportFinding is the stable json shape for a finding in the -json report. it's
// a dedicated view, not the Finding struct itself, so severity renders as its
// string name and the on-disk snapshot format (which marshals Finding directly)
// stays untouched. confidence is omitted when zero so recon findings without a
// detection score don't carry a misleading 0.
type reportFinding struct {
Target string `json:"target"`
Module string `json:"module"`
Severity string `json:"severity"`
Key string `json:"key"`
Title string `json:"title"`
Evidence string `json:"evidence,omitempty"`
Confidence float32 `json:"confidence,omitempty"`
}
// JSONReport serializes a run's normalized findings to an indented json array.
// it never returns a nil body: an empty run marshals to "[]" so consumers can
// always parse the output.
func JSONReport(findings []Finding) ([]byte, error) {
out := make([]reportFinding, 0, len(findings))
for i := 0; i < len(findings); i++ {
f := findings[i]
out = append(out, reportFinding{
Target: f.Target,
Module: f.Module,
Severity: f.Severity.String(),
Key: f.Key,
Title: f.Title,
Evidence: f.Raw,
Confidence: f.Confidence,
})
}
return json.MarshalIndent(out, "", " ")
}