gitleaks/gitleaks
report
Active contributors: Zachary Rice, Richard Gomez
Purpose
report/ defines Finding (the structured representation of a leak) and the Reporter interface plus five built-in implementations: JSON, CSV, JUnit, SARIF, and a Go text/template renderer.
Directory layout
report/
├── report.go # Reporter interface (a single `Write` method)
├── finding.go # Finding + RequiredFinding types, redaction
├── constants.go # driver/version constants for SARIF
├── json.go # JsonReporter
├── csv.go # CsvReporter
├── junit.go # JunitReporter
├── sarif.go # SarifReporter (the most fully-typed one)
└── template.go # TemplateReporter using text/template + sprigKey abstractions
| Symbol | File | Description |
|---|---|---|
Reporter |
report.go |
One method: Write(w io.WriteCloser, findings []Finding) error |
Finding |
finding.go |
The structured leak: rule ID, file, line/column, match, secret, commit metadata, fingerprint, tags |
RequiredFinding |
finding.go |
A subset of Finding carried inside a primary finding when composite rules fire |
Finding.Redact(percent) |
finding.go |
Mask a percentage of the secret (or replace with REDACTED at 100) |
JsonReporter, CsvReporter, JunitReporter, SarifReporter |
per file | The four built-ins |
TemplateReporter |
template.go |
text/template-based custom output |
NewTemplateReporter(path) |
template.go |
Loads a template file, registers sprig functions, returns the reporter |
StdoutReportPath |
(constant) | -, used to direct output to stdout instead of a file |
How it works
The reporter is selected in cmd/root.go's Detector(...) constructor. The selection logic:
- If
--report-formatis set, use that. - Otherwise, infer from the
--report-pathextension:.csv,.json,.sarifare auto-detected. Other extensions fail. - If
--report-format=template, the--report-templateflag must point at a Go template file.
The chosen reporter is stored on Detector.Reporter. After scanning, findingSummaryAndExit opens the report path (or stdout if it's -) and calls reporter.Write(file, findings).
graph LR
Flags[--report-format<br/>--report-path] --> Sel[reporter selection]
Sel --> JR[JsonReporter]
Sel --> CR[CsvReporter]
Sel --> JU[JunitReporter]
Sel --> SA[SarifReporter]
Sel --> TP[TemplateReporter]
Findings[Detector.findings] --> Wr[reporter.Write]
Wr --> Out[file or stdout]JSON
JsonReporter (report/json.go) is a one-line implementation — json.NewEncoder(w).SetIndent("", " ").Encode(findings). It's the most common format and is what baselines consume.
CSV
CsvReporter (report/csv.go) writes a header row and one data row per finding using encoding/csv.
JUnit
JunitReporter (report/junit.go) emits a JUnit XML test report so CI systems can surface findings in their test output. Each finding becomes a failing test case keyed on the rule ID.
SARIF
SarifReporter (report/sarif.go) is the most fully-typed reporter — it builds a SARIF 2.1.0 document conforming to the schema at https://json.schemastore.org/sarif-2.1.0.json. Notable details:
- The
tool.driver.rulesarray is populated fromConfig.GetOrderedRules()so ordering is stable across runs. partialFingerprintscarries commit metadata (sha, email, message, date, author) so SARIF consumers like GitHub Code Scanning can deduplicate across runs.- Empty rule lists are explicitly rendered as
[](notnull) for consumers that don't toleratenull.
Template
TemplateReporter (report/template.go) takes a --report-template path, reads its contents, parses it as a Go text/template, and registers the Masterminds/sprig function map minus env, expandenv, and getHostByName (these are removed for security; templates shouldn't have access to environment variables or the network).
Finding
type Finding struct {
RuleID, Description string
StartLine, EndLine, StartColumn, EndColumn int
Line, Match, Secret string
File, SymlinkFile, Commit string
Link string `json:",omitempty"`
Entropy float32
Author, Email, Date, Message string
Tags []string
Fingerprint string
Fragment *sources.Fragment `json:",omitempty"`
requiredFindings []*RequiredFinding // unexported; printed via PrintRequiredFindings
}A few choices worth noting:
Lineis excluded from JSON output (json:"-") because it can leak surrounding context the user didn't intend to share.Fragmentis included as a pointer so it can be nil — it's there for library consumers who want extra context (e.g., for ML-based post-filtering, mentioned in the comment as "eventually ML validation").requiredFindingsis unexported "during experimental phase" per the comment; onlyPrintRequiredFindingsandAddRequiredFindingssee it from outside.
Redaction
Finding.Redact(percent):
- For
percent ≥ 100, replacesSecretwith the literal stringREDACTED. - For
percent < 100, keeps the first(1 - percent/100) * len(Secret)characters and appends.... - Replaces every occurrence of the original secret in
LineandMatchwith the masked version, so logs and printed findings don't accidentally leak the value.
The --redact flag in cmd/root.go accepts a uint between 0 and 100; passing the flag with no value defaults to 100 (rootCmd.Flag("redact").NoOptDefVal = "100").
Integration points
detect/populates the[]Findingand stores the reporter onDetector.Reporter.cmd/root.gochooses the reporter and opens the output writer.config/is consulted by the SARIF reporter throughConfig.GetOrderedRules().Masterminds/sprigpowers the template reporter's function map.
Entry points for modification
- Adding a new format: implement
Reporterwith aWrite(w, findings)method, and register it incmd/root.go's reporter switch (case "yourformat": reporter = ...). Keep extension inference in mind. - Adding a Finding field: thread it through
Finding, populate it indetect/detect.go'sdetectRule(or wherever the finding originates), and update each reporter that should surface it. Note that the JSON tags onFindingare inferred from struct field names — name new fields carefully, since they become public schema. - Tightening template safety:
template.goalready removesenv,expandenv, andgetHostByNamefrom the sprig function map. If you need to remove more (e.g., file I/O helpers),delete(funcMap, "name")after the sprig import.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.