Documentation
¶
Overview ¶
Package sarif provides Draugr's result currency: a pragmatic model of SARIF 2.1.0 findings, plus merge and deduplication. Every scanner normalizes its output to a Report; the engine merges reports and the result can be serialized to standard SARIF JSON for GitHub / Azure DevOps / GitLab.
Index ¶
Constants ¶
const Version = "2.1.0"
Version is the SARIF specification version Draugr emits.
Variables ¶
This section is empty.
Functions ¶
func DerivedHelpURI ¶ added in v0.35.0
DerivedHelpURI maps identifiers with a stable, publicly resolvable home to their advisory. It's the fallback for scanners that publish no rule metadata; anything unrecognized gets "".
Types ¶
type Level ¶
type Level string
Level is the severity of a result, mirroring SARIF's result.level.
const ( LevelError Level = "error" LevelWarning Level = "warning" LevelNote Level = "note" LevelNone Level = "none" )
The SARIF result levels.
type Location ¶
type Location struct {
URI string `json:"uri,omitempty"`
StartLine int `json:"startLine,omitempty"`
}
Location points at where a finding was observed.
type MarshalOptions ¶ added in v0.35.0
type MarshalOptions struct {
// Compact drops what only a human reads — indentation, and the rule prose relayed from
// the scanner — while keeping the report valid SARIF.
//
// It exists for a consumer that is going to *act* on the report rather than read it,
// typically an agent paying for every byte of context. Rule descriptions and remediation
// text are the bulk of a Draugr report (61% of it, measured on this repo), and a reader
// that can follow a link doesn't need them inlined. So helpUri survives compaction and the
// prose doesn't: keep the pointer, drop the paragraphs.
Compact bool
}
MarshalOptions tunes how a report is serialized. The zero value is the default: indented, with everything a person or an editor might want.
type Report ¶
type Report struct {
Tool string `json:"tool,omitempty"`
Results []Result `json:"results"`
// Rules is the metadata the scanner published about the rules it applied, keyed by rule id.
// A result names its rule; the rule is what explains it. Carrying this through is what lets
// a reader — in a terminal, an editor, or a pull request — find out what "DS-0002" means.
// Not every scanner publishes it, so entries may be missing.
Rules map[string]Rule `json:"rules,omitempty"`
}
Report is a set of findings, normalized to SARIF semantics. Tool names the primary scanner; when a report carries results from several tools (after Merge), each Result keeps its own Tool.
func FromSARIF ¶
FromSARIF parses standard SARIF 2.1.0 JSON into a Report, flattening all runs and setting each result's Tool from its run's driver name.
func Merge ¶
Merge combines reports into one, deduplicating results by fingerprint and preserving first-seen order. Each result's Tool is backfilled from its source report when unset.
func (Report) Dedup ¶
Dedup returns a copy with exact-duplicate results removed, preserving first-seen order.
func (Report) HelpURI ¶ added in v0.35.0
HelpURI returns where a reader can look up ruleID: what the scanner published, or a URL derived from a well-known identifier scheme when it published nothing. Empty when we can't say — a wrong link is worse than none.
func (Report) Highest ¶
Highest returns the most severe level present, or LevelNone when there are no results.
func (Report) MarshalSARIF ¶
MarshalSARIF serializes the report to standard SARIF 2.1.0 JSON as a single "Draugr" run, with each result's originating scanner recorded in its property bag ("tool").
func (Report) MarshalSARIFWith ¶ added in v0.35.0
func (r Report) MarshalSARIFWith(opts MarshalOptions) ([]byte, error)
MarshalSARIFWith is MarshalSARIF with explicit options.
type Result ¶
type Result struct {
// Tool is the scanner that produced the finding.
Tool string `json:"tool,omitempty"`
RuleID string `json:"ruleId"`
Level Level `json:"level"`
Message string `json:"message"`
Location Location `json:"location,omitempty"`
// Score is the finding's numeric CVSS-style severity (0–10), sourced from the SARIF
// "security-severity" property. HasScore reports whether a score was present; without
// one, normalized Severity falls back to Level.
Score float64 `json:"score,omitempty"`
HasScore bool `json:"-"`
// Priority is the computed action band (P1–P4) for this finding, stamped by the engine
// from the component's risk classification. Empty when prioritization is not configured.
Priority string `json:"priority,omitempty"`
// Suppression is set when a Saga exclusion matched this finding. A suppressed result is
// reported but not counted: it does not reach Counts, the verdict, or the fix-first list.
// Nil for an active finding.
Suppression *Suppression `json:"suppression,omitempty"`
}
Result is a single finding.
func (Result) Fingerprint ¶
Fingerprint is a stable identifier for deduplication: two results with the same fingerprint are considered the same finding.
func (Result) Severity ¶ added in v0.5.0
Severity resolves a finding's normalized severity, in the order the SARIF/prioritization design prescribes:
- the finding's numeric score (CVSS / SARIF security-severity), if present;
- otherwise its SARIF level;
- then raised to floor if floor is more severe (a control-default floor, e.g. a leaked secret is never "low"). Pass an empty floor for no floor.
func (Result) Suppressed ¶ added in v0.42.0
Suppressed reports whether this finding was excluded by a Saga rule.
type Rule ¶ added in v0.35.0
type Rule struct {
// Name is a human-readable identifier (SARIF reportingDescriptor.name), where the id
// itself is opaque.
Name string `json:"name,omitempty"`
// ShortDescription is a single sentence; FullDescription is a paragraph.
ShortDescription string `json:"shortDescription,omitempty"`
FullDescription string `json:"fullDescription,omitempty"`
// Help is remediation guidance, often Markdown.
Help string `json:"help,omitempty"`
// HelpURI points at the rule's documentation or advisory.
HelpURI string `json:"helpUri,omitempty"`
}
Rule is what a scanner says about one of its rules, beyond the bare id. Every field is optional: scanners vary widely in how much they publish, and an absent field is normal.
type Severity ¶ added in v0.5.0
type Severity string
Severity is Draugr's normalized, cross-control severity ladder. Unlike Level (the SARIF wire values error/warning/note), Severity is what prioritization ranks on: it splits a numeric CVSS-style score into four bands so a dependency CVE, a leaked secret, and an IaC misconfiguration can share one ordered list. See docs/concepts.md (prioritization).
const ( SeverityCritical Severity = "critical" SeverityHigh Severity = "high" SeverityMedium Severity = "medium" SeverityLow Severity = "low" )
Severity bands, from most to least severe.
type Suppression ¶ added in v0.42.0
type Suppression struct {
// Kind is the SARIF suppression kind. Draugr writes "external": the decision came from the
// Saga, not from an annotation in the source.
Kind string `json:"kind"`
// Justification is the reason the Saga gave. Required by Draugr even though SARIF allows
// it to be absent.
Justification string `json:"justification"`
}
Suppression records that a finding was excluded, and why.