Skip to content

feat: add SARIF 2.1.0 output (-f sarif)#34

Open
ChrisJr404 wants to merge 1 commit intoknostic:masterfrom
ChrisJr404:feat/sarif-output-report-format
Open

feat: add SARIF 2.1.0 output (-f sarif)#34
ChrisJr404 wants to merge 1 commit intoknostic:masterfrom
ChrisJr404:feat/sarif-output-report-format

Conversation

@ChrisJr404
Copy link
Copy Markdown

Adds -f sarif to openant report. Emits a SARIF 2.1.0 log so a scan can be uploaded to GitHub Code Scanning or GitLab SAST without writing a converter, which is the format every other SAST in this category supports.

Implementation mirrors -f html: Python's report-data returns the same pre-computed JSON we already use for HTML, and the SARIF emitter is purely Go-side (no LLM round-trip, deterministic). Findings become SARIF results, verdicts get hoisted into a synthesized rules list. vulnerable and bypassable surface as level error, inconclusive and unclear as warning, everything else as note.

Couple of choices worth calling out:

  • No startLine in the location region. The current Finding struct only carries file + function, so I omit the region rather than emit a synthetic line 1 (which would anchor alerts to the wrong row in Code Scanning). When line numbers eventually land in ReportData, the region payload in sarifLocationFor is the only thing that needs to grow.
  • Each result carries a partialFingerprints entry keyed openant/file/function/verdict/v1, so successive scans dedupe cleanly in Code Scanning instead of opening fresh alerts each run.
  • Rules are synthesized per verdict since findings aren't keyed by a stable per-rule taxonomy yet. Categories from ReportData.Categories supply the descriptions, falling back to a generic blurb if a verdict has no category entry.
  • versionControlProvenance is emitted when ReportData.RepoURL is set, including revisionId from CommitSHA if available. Skipped entirely otherwise so we don't write a half-empty object.

Default output path is <resultsDir>/final-reports/report.sarif, matching the HTML default's directory layout.

15 unit tests in internal/report/sarif_test.go cover envelope shape, rule dedup, level mapping, path normalization (./ strip + backslash conversion), logical location, dynamic test property propagation, fingerprint stability, VCS provenance gating, the empty-AttackVector fallback that keeps message.text non-empty per spec, the 4 KiB message cap, and an end-to-end round-trip through json.Unmarshal to confirm the emitted log is valid JSON.

go test ./... is green; gofmt and go vet are clean.

Open to a different flag shape if you'd rather. Could be a flag on scan so it lands alongside pipeline_output.json automatically, or the rule synthesis can be split into something more granular if per-verdict rules feel too coarse for Code Scanning's per-rule severity controls.

Lets `openant report -f sarif results_verified.json` emit a SARIF log
that GitHub Code Scanning and GitLab SAST can ingest without a
converter, matching what every other SAST in this category supports.

Renders Go-side via the same flow as -f html: Python's `report-data`
subcommand returns pre-computed JSON, and BuildSARIF turns ReportData
into a SARIF map. Findings become results, verdicts get synthesized
into a `rules` array (vulnerable+bypassable as level `error`,
inconclusive/unclear as `warning`, everything else as `note`). File
paths land as artifactLocation.uri without a startLine, since the
current Finding struct doesn't carry line numbers and emitting a
synthetic 1 would anchor alerts to the wrong row in Code Scanning.

Each result carries a partialFingerprints entry keyed
"openant/file/function/verdict/v1" so re-runs dedupe cleanly, and
versionControlProvenance is populated when ReportData.RepoURL is set
(including revisionId from CommitSHA when available).

15 unit tests cover envelope shape, rule dedup by verdict, level
mapping, path normalization, logical location, dynamic test
property propagation, fingerprint stability, VCS provenance
gating, the empty-AttackVector fallback that keeps message.text
non-empty per spec, the 4 KiB message cap, and an end-to-end
round-trip through json.Unmarshal.
@ChrisJr404 ChrisJr404 force-pushed the feat/sarif-output-report-format branch from db4edb8 to e4122c3 Compare May 5, 2026 22:23
@ChrisJr404 ChrisJr404 changed the title report: add SARIF 2.1.0 output (-f sarif) feat: add SARIF 2.1.0 output (-f sarif) May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant