anchore/grype
Presenters
Active contributors: Alex Goodman, Will Murphy, Keith Zantow
Purpose
Presenters render the result of a Grype scan in one of several formats. They are the boundary between the matcher pipeline (which produces typed Go values) and the bytes the user actually sees.
Directory layout
grype/presenter/
├── presenter.go # GetPresenter shim (deprecated)
├── models/ # JSON model — the shared serialization types
├── table/ # default human-readable table output
├── json/ # JSON output (the schema source of truth)
├── cyclonedx/ # CycloneDX (JSON + XML, plus embedded-VEX variants)
├── sarif/ # SARIF for code-scanning integrations
├── template/ # arbitrary user-supplied Go template
├── explain/ # explain subcommand renderer (post-scan)
└── internal/ # shared rendering helpers
internal/format/
└── format.go # format name → presenter mapping (the modern entry point)How presenters are selected
internal/format is the modern entry point. cmd/grype/cli/commands/root.go::runGrype builds a format.MakeScanResultWriter that fans output to one or more Outputs:
writer, err := format.MakeScanResultWriter(opts.Outputs, opts.File, format.PresentationConfig{
TemplateFilePath: opts.OutputTemplateFile,
ShowSuppressed: opts.ShowSuppressed,
Pretty: opts.Pretty,
})opts.Outputs is a slice of <format>=<destination> strings (json=report.json, table, sarif=findings.sarif, etc.). format.GetPresenter picks the right presenter.Presenter per format. The legacy grype/presenter/presenter.go::GetPresenter is a thin shim and is annotated // Deprecated: this will be removed in v1.0.
Available formats
| Format name | Path | Notes |
|---|---|---|
table (default) |
grype/presenter/table/ |
Human-readable table with optional color. |
json |
grype/presenter/json/ |
The canonical machine-readable format; schema is generated. |
cyclonedx-json, cyclonedx-xml |
grype/presenter/cyclonedx/ |
CycloneDX 1.5+. |
embedded-cyclonedx-vex-json, embedded-cyclonedx-vex-xml |
grype/presenter/cyclonedx/ |
CycloneDX with vulnerabilities embedded as VEX statements. |
sarif |
grype/presenter/sarif/ |
For GitHub code scanning, etc. |
template |
grype/presenter/template/ |
User-supplied Go text/template. |
The shared model
grype/presenter/models/ defines the JSON-shaped types every presenter starts from:
Document— top-level wrapper.Match— a flattened, presentation-friendly version ofmatch.Match.Source— the scan target description.Distro— distro fields.Configuration,DBStatus,Provenance— context fields.
PresenterConfig carries everything a presenter needs:
- The matched
match.Matches,[]match.IgnoredMatch, and[]pkg.Package. - The original
*sbom.SBOM(for CycloneDX presenters that want to emit a complete BOM). pkg.Context, DB status, applied VEX rules.
Most presenters operate on the models.Document after a one-time conversion via models.NewDocument.
CycloneDX peculiarities
CycloneDX has two modes:
- Plain CycloneDX — emit a SBOM plus a
vulnerabilitiesarray. - Embedded VEX — emit each vulnerability as a CycloneDX VEX statement so that the resulting BOM can be both consumed as a SBOM and as a VEX document.
Both share machinery in grype/presenter/cyclonedx/. The embedded-VEX variants are why Grype keeps the original SBOM around end-to-end — the presenter needs the unmodified BOM contents to stitch in vulnerability findings.
SARIF
SARIF output (for GitHub code scanning) is generated via owenrumney/go-sarif. Each match becomes a SARIF result; severities map to SARIF levels. The presenter emits a single SARIF run per scan.
Template presenter
grype/presenter/template/ exposes the canonical model to a user-supplied text/template. Helper functions come from Masterminds/sprig. Example templates can be found in templates/.
The template presenter is the escape hatch for one-off output formats; users who need stable, structured output should prefer json.
Explain (post-scan)
grype/presenter/explain/ is different from the other presenters: it does not run as part of grype <target>. Instead, it powers the grype explain subcommand, which reads a JSON document on stdin and produces a per-match natural-language rationale.
This split keeps the explain logic away from the hot scan path and lets users re-explain old reports without re-scanning.
JSON schema
The JSON presenter's shape is the public API of Grype's machine-readable output. A separate generator under cmd/grype/cli/commands/internal/jsonschema/ produces a JSON Schema from the model types; task check-json-schema-drift fails the build if the committed schema and the regenerated one disagree.
Key abstractions
| Symbol | Where | Description |
|---|---|---|
format.PresentationConfig |
internal/format/ |
Per-output format configuration. |
format.MakeScanResultWriter |
internal/format/ |
Creates a multi-format io.Writer. |
format.GetPresenter(format, cfg, pcfg) |
internal/format/ |
Resolves a format name to a presenter. |
models.PresenterConfig |
grype/presenter/models/ |
Bundle of inputs every presenter needs. |
models.Document |
grype/presenter/models/ |
The canonical JSON-shaped document. |
Key source files
| File | Purpose |
|---|---|
internal/format/format.go |
Format-name → presenter dispatch (modern entry). |
grype/presenter/models/ |
Shared serialization types. |
grype/presenter/json/presenter.go |
JSON output (source of the public schema). |
grype/presenter/cyclonedx/presenter.go |
CycloneDX + embedded-VEX. |
grype/presenter/sarif/presenter.go |
SARIF. |
grype/presenter/template/presenter.go |
Go-template-based output. |
grype/presenter/table/presenter.go |
Default table renderer. |
Entry points for modification
- Add a new format — create a sibling directory under
grype/presenter/, implementpresenter.Presenter, register the format ininternal/format/format.go. - Change JSON shape — modify
grype/presenter/models/, regenerate the schema withtask generate-json-schema, and bump the schema version. The drift checker will fail the build until both are consistent. - Add a new column to the table presenter — modify
grype/presenter/table/. Snapshot tests (under__snapshots__/) need updating withtask unit -update-snaps.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.