export

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package export builds deterministic SARIF 2.1.0 + OpenVEX documents from stored findings. Templated from data – no LLM in the report path.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MarshalSARIF

func MarshalSARIF(findings []finding.Finding, version string, opts SARIFOptions) ([]byte, error)

MarshalSARIF renders findings as an indented SARIF 2.1.0 log – the artifact a code-scanning uploader (e.g. GitHub `codeql-action/upload-sarif`) consumes. It is deterministic and templated purely from stored findings: no clock, no LLM (golden rule 5). version is the synapse driver version recorded on the run's tool driver. opts carries optional per-finding resolvers: Manifest gives SCA findings a physical location (a repo-relative manifest path), Fix adds the remediating version, and AIGateExemption explains policy-authorized external suppression without removing the result. All are nil-safe; pass the zero SARIFOptions to enrich nothing.

Types

type CSAFDoc added in v0.2.0

type CSAFDoc struct {
	Document CSAFDocument `json:"document"`
	// product_tree and vulnerabilities are omitted when empty rather than emitted as `[]`, which CSAF
	// rejects (its arrays must be non-empty when present).
	ProductTree     *CSAFProductTree    `json:"product_tree,omitempty"`
	Vulnerabilities []CSAFVulnerability `json:"vulnerabilities,omitempty"`
}

type CSAFDocument added in v0.2.0

type CSAFDocument struct {
	Category    string        `json:"category"`
	CSAFVersion string        `json:"csaf_version"`
	Publisher   CSAFPublisher `json:"publisher"`
	Title       string        `json:"title"`
	Tracking    CSAFTracking  `json:"tracking"`
}

type CSAFEngine added in v0.2.0

type CSAFEngine struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

type CSAFFlag added in v0.2.0

type CSAFFlag struct {
	Label      string   `json:"label"`
	ProductIDs []string `json:"product_ids"`
}

type CSAFGenerator added in v0.2.0

type CSAFGenerator struct {
	Engine CSAFEngine `json:"engine"`
}

type CSAFProductName added in v0.2.0

type CSAFProductName struct {
	ProductID string `json:"product_id"`
	Name      string `json:"name"`
}

type CSAFProductStatus added in v0.2.0

type CSAFProductStatus struct {
	KnownAffected      []string `json:"known_affected,omitempty"`
	KnownNotAffected   []string `json:"known_not_affected,omitempty"`
	Fixed              []string `json:"fixed,omitempty"`
	UnderInvestigation []string `json:"under_investigation,omitempty"`
}

type CSAFProductTree added in v0.2.0

type CSAFProductTree struct {
	FullProductNames []CSAFProductName `json:"full_product_names"`
}

type CSAFPublisher added in v0.2.0

type CSAFPublisher struct {
	Category  string `json:"category"`
	Name      string `json:"name"`
	Namespace string `json:"namespace"`
}

type CSAFRevision added in v0.2.0

type CSAFRevision struct {
	Number  string `json:"number"`
	Date    string `json:"date"`
	Summary string `json:"summary"`
}

type CSAFTracking added in v0.2.0

type CSAFTracking struct {
	ID                 string         `json:"id"`
	Status             string         `json:"status"`
	Version            string         `json:"version"`
	InitialReleaseDate string         `json:"initial_release_date"`
	CurrentReleaseDate string         `json:"current_release_date"`
	Generator          CSAFGenerator  `json:"generator"`
	RevisionHistory    []CSAFRevision `json:"revision_history"`
}

type CSAFVulnID added in v0.2.0

type CSAFVulnID struct {
	SystemName string `json:"system_name"`
	Text       string `json:"text"`
}

type CSAFVulnerability added in v0.2.0

type CSAFVulnerability struct {
	CVE           string            `json:"cve,omitempty"`
	IDs           []CSAFVulnID      `json:"ids,omitempty"`
	Flags         []CSAFFlag        `json:"flags,omitempty"`
	ProductStatus CSAFProductStatus `json:"product_status"`
}

type ReachabilityEvidence added in v0.2.0

type ReachabilityEvidence struct {
	Source string                    `json:"source"` // always "reachability"
	Label  ReachabilityLabel         `json:"label"`
	Tier   judgment.ReachabilityTier `json:"tier,omitempty"`
	Path   []string                  `json:"path,omitempty"`
}

ReachabilityEvidence is the tagged evidence item a finding renders for its reachability posture, adopting the Snyk evidence[] contract (source-tagged evidence beside the dependency path). Source is always "reachability"; Label is the derived four-state label; Tier is the proving tier when a judgment decided it; Path is the call/exploit path from the winning claim (empty when none / not reachable).

func DeriveReachabilityEvidence added in v0.2.0

func DeriveReachabilityEvidence(judgments []judgment.Judgment, findingID string) *ReachabilityEvidence

DeriveReachabilityEvidence derives a finding's reachability evidence from its PUBLISHABLE, finding-scoped reachability judgments (the same publishability gate the VEX path uses). It selects the winning claim with the shared state-aware ordering (judgment.ReachabilityClaim.Supersedes, EPIC #1042 A-CORE), so an unproven negative never shadows a reachable, then maps it to a derived label:

  • a winning REACHABLE claim -> reachable (with its call path);
  • a winning proven not_reachable (SuppressesFinding) -> present_unreached;
  • a winning inconclusive claim, or NO reachability judgment at all -> no_analysis.

It never mints conditionally_reachable (reserved for the conditional engine). It ALWAYS returns a non-nil evidence item so every finding carries an explicit reachability posture (no_analysis when nothing conclusive ran), never a silently-absent one. Deriving at the surface keeps the domain verdict enum unchanged.

type ReachabilityLabel added in v0.2.0

type ReachabilityLabel string

ReachabilityLabel is the closed, user-visible reachability vocabulary rendered as a tagged evidence item (EPIC #1042, 0.2). It is DERIVED at the surface from a finding's reachability judgments; it is not a domain verdict and does not change the ReachabilityState enum (which stays reachable|not_reachable| unknown). The wire values match the reachbench label vocabulary so the benchmark and the public export speak one contract, and the OpenAPI enum is the authoritative public schema.

const (
	// LabelReachable: a PUBLISHABLE reachable judgment (any tier) is the winning claim. The vulnerable code
	// is reached; the call/exploit path is carried alongside.
	LabelReachable ReachabilityLabel = "reachable"
	// LabelConditionallyReachable: reachable only under a precondition (a taint label / guard). Reserved for
	// the conditional-reachability engine; not emitted until that lands.
	LabelConditionallyReachable ReachabilityLabel = "conditionally_reachable"
	// LabelPresentUnreached: a SOUND proof of non-reachability (SuppressesFinding). The vulnerable code is
	// present in a matched dependency but proven not reached.
	LabelPresentUnreached ReachabilityLabel = "present_unreached"
	// LabelNoAnalysis: no conclusive reachability analysis for this finding, either because no reachability
	// judgment exists or the strongest one is inconclusive (unknown / unproven). Distinct from
	// present_unreached: absence of analysis is never reported as a proven-unreached result.
	LabelNoAnalysis ReachabilityLabel = "no_analysis"
)

type SARIFArtifactLocation

type SARIFArtifactLocation struct {
	URI string `json:"uri"` // repo-relative path (GitHub matches it against the PR diff)
}

type SARIFCodeFlow added in v0.2.0

type SARIFCodeFlow struct {
	ThreadFlows []SARIFThreadFlow `json:"threadFlows"`
}

type SARIFConfig

type SARIFConfig struct {
	Level string `json:"level"`
}

type SARIFDriver

type SARIFDriver struct {
	Name           string      `json:"name"`
	Version        string      `json:"version"`
	InformationURI string      `json:"informationUri,omitempty"`
	Rules          []SARIFRule `json:"rules"`
}

type SARIFLocation

type SARIFLocation struct {
	// A first-party finding (SAST/secret/misconfig) has a source file:line -> physicalLocation, so a
	// code-scanning UI annotates the exact line. An SCA finding is about a dependency, not a source
	// line -> logicalLocation module. Exactly one is set per location.
	PhysicalLocation *SARIFPhysicalLocation `json:"physicalLocation,omitempty"`
	LogicalLocations []SARIFLogicalLocation `json:"logicalLocations,omitempty"`
}

type SARIFLog

type SARIFLog struct {
	Schema  string     `json:"$schema"`
	Version string     `json:"version"`
	Runs    []SARIFRun `json:"runs"`
}

type SARIFLogicalLocation

type SARIFLogicalLocation struct {
	Name string `json:"name"`
	Kind string `json:"kind,omitempty"`
}

type SARIFOptions

type SARIFOptions struct {
	// Manifest returns the repo-relative manifest/lockfile that declares a dependency finding's
	// component, so the result gets a physical location a code-scanning UI can annotate. "" when unknown.
	Manifest func(finding.Finding) string
	// Fix returns the version that remediates a dependency finding. "" when there is no fix or it is unknown.
	Fix func(finding.Finding) string
	// AIGateExemption returns policy metadata only when the finding's exemption has already passed the
	// server-owned authorization re-check. SARIF renders it as an external accepted suppression while
	// retaining the result. Advisory or review-required opinions must return false.
	AIGateExemption func(finding.Finding) (ports.AIGateExemption, bool)
}

SARIFOptions carries optional per-finding resolvers. Every field is nil-safe.

type SARIFPhysicalLocation

type SARIFPhysicalLocation struct {
	ArtifactLocation SARIFArtifactLocation `json:"artifactLocation"`
	Region           *SARIFRegion          `json:"region,omitempty"`
}

type SARIFRegion

type SARIFRegion struct {
	StartLine   int `json:"startLine"` // 1-based; SARIF requires >= 1
	StartColumn int `json:"startColumn,omitempty"`
}

type SARIFResult

type SARIFResult struct {
	RuleID       string             `json:"ruleId"`
	Level        string             `json:"level"`
	Message      SARIFText          `json:"message"`
	Locations    []SARIFLocation    `json:"locations,omitempty"`
	CodeFlows    []SARIFCodeFlow    `json:"codeFlows,omitempty"`
	Suppressions []SARIFSuppression `json:"suppressions,omitempty"`
	Properties   map[string]any     `json:"properties,omitempty"`
}

type SARIFRule

type SARIFRule struct {
	ID                   string       `json:"id"`
	ShortDescription     SARIFText    `json:"shortDescription"`
	HelpURI              string       `json:"helpUri,omitempty"`
	DefaultConfiguration *SARIFConfig `json:"defaultConfiguration,omitempty"`
}

type SARIFRun

type SARIFRun struct {
	Tool    SARIFTool     `json:"tool"`
	Results []SARIFResult `json:"results"`
}

type SARIFSuppression added in v0.1.8

type SARIFSuppression struct {
	Kind          string `json:"kind"`
	Status        string `json:"status,omitempty"`
	Justification string `json:"justification,omitempty"`
}

type SARIFText

type SARIFText struct {
	Text string `json:"text"`
}

type SARIFThreadFlow added in v0.2.0

type SARIFThreadFlow struct {
	Locations []SARIFThreadFlowLocation `json:"locations"`
}

type SARIFThreadFlowLocation added in v0.2.0

type SARIFThreadFlowLocation struct {
	Location SARIFLocation `json:"location"`
}

type SARIFTool

type SARIFTool struct {
	Driver SARIFDriver `json:"driver"`
}

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service renders an engagement's findings as SARIF or OpenVEX.

func NewService

func NewService(findings ports.FindingRepository, clock ports.Clock, version string) *Service

NewService wires the export use case.

func (*Service) CSAFVEX added in v0.2.0

func (s *Service) CSAFVEX(ctx context.Context, engagementID shared.ID) (*CSAFDoc, error)

CSAFVEX returns the same publishable findings as a CSAF 2.0 VEX document, the enterprise-standard companion to OpenVEX. It asserts exactly what OpenVEX asserts, reshaped into CSAF's product-tree + per-vulnerability product-status model.

func (*Service) OpenVEX

func (s *Service) OpenVEX(ctx context.Context, engagementID shared.ID, supersedes string) (*VEXDoc, error)

OpenVEX returns the engagement's vulnerability findings as an OpenVEX 0.2 document. It reads through the publishability gate – consistent with SARIF and the report path – so an unproven exploitation finding is never asserted in a VEX statement. supersedes, when non-empty, is the @id of a prior document this one replaces (the caller who re-exports knows it); the document's own @id is content-addressed, so an unchanged re-export is idempotent.

func (*Service) SARIF

func (s *Service) SARIF(ctx context.Context, engagementID shared.ID) (*SARIFLog, error)

SARIF returns the engagement's findings as a SARIF 2.1.0 log. It reads through the publishability gate so an unproven exploitation finding never ships in the exported log.

func (*Service) SetAIGateExemptions added in v0.1.8

func (s *Service) SetAIGateExemptions(reader ports.AIGateExemptionReader)

SetAIGateExemptions wires the latest-scan policy projection used to annotate retained SARIF results. nil keeps legacy exports unannotated.

func (*Service) SetJudgments

func (s *Service) SetJudgments(j judgmentReader)

SetJudgments wires the reachability-judgment reader so OpenVEX picks the not_affected justification by reachability tier. nil ⇒ the default justification.

type VEXDoc

type VEXDoc struct {
	Context    string         `json:"@context"`
	ID         string         `json:"@id"`
	Author     string         `json:"author"`
	Timestamp  string         `json:"timestamp"`
	Version    int            `json:"version"`
	Tooling    string         `json:"tooling,omitempty"`
	Supersedes []VEXDocRef    `json:"supersedes,omitempty"`
	Statements []VEXStatement `json:"statements"`
}

type VEXDocRef added in v0.2.0

type VEXDocRef struct {
	ID string `json:"@id"`
}

VEXDocRef references a prior document this one supersedes.

type VEXProduct

type VEXProduct struct {
	ID string `json:"@id"`
}

type VEXStatement

type VEXStatement struct {
	Vulnerability VEXVuln      `json:"vulnerability"`
	Products      []VEXProduct `json:"products"`
	Status        string       `json:"status"`
	Justification string       `json:"justification,omitempty"`
	// Timestamp is the per-statement assertion time (when the finding's status was last evaluated). Per the
	// OpenVEX spec a statement without one inherits the document timestamp; emitting it explicitly lets a
	// consumer age each assertion independently.
	Timestamp string `json:"timestamp,omitempty"`
}

type VEXVuln

type VEXVuln struct {
	Name string `json:"name"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL