package predicate import ( "context" "encoding/json" "fmt" "io" "time" "github.com/package-url/packageurl-go" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/clock" "github.com/aquasecurity/trivy/pkg/types" ) // CosignVulnPredicate represents the Cosign Vulnerability Scan Record. // CosignVulnPredicate is based on structures in the Cosign repository. // We defined them ourselves to reduce our dependence on the repository. // cf. https://github.com/sigstore/cosign/blob/e0547cff64f98585a837a524ff77ff6b47ff5609/pkg/cosign/attestation/attestation.go#L45-L50 type CosignVulnPredicate struct { Invocation Invocation `json:"invocation"` Scanner Scanner `json:"scanner"` Metadata Metadata `json:"metadata"` } type Invocation struct { Parameters any `json:"parameters"` URI string `json:"uri"` EventID string `json:"event_id"` BuilderID string `json:"builder.id"` } type DB struct { URI string `json:"uri"` Version string `json:"version"` } type Scanner struct { URI string `json:"uri"` Version string `json:"version"` DB DB `json:"db"` Result types.Report `json:"result"` } type Metadata struct { ScanStartedOn time.Time `json:"scanStartedOn"` ScanFinishedOn time.Time `json:"scanFinishedOn"` } type VulnWriter struct { output io.Writer version string } func NewVulnWriter(output io.Writer, version string) VulnWriter { return VulnWriter{ output: output, version: version, } } func (w VulnWriter) Write(ctx context.Context, report types.Report) error { predicate := CosignVulnPredicate{} purl := packageurl.NewPackageURL("github", "aquasecurity", "trivy", w.version, nil, "") predicate.Scanner = Scanner{ URI: purl.ToString(), Version: w.version, Result: report, } now := clock.Now(ctx) predicate.Metadata = Metadata{ ScanStartedOn: now, ScanFinishedOn: now, } output, err := json.MarshalIndent(predicate, "", " ") if err != nil { return xerrors.Errorf("failed to marshal cosign vulnerability predicate: %w", err) } if _, err = fmt.Fprint(w.output, string(output)); err != nil { return xerrors.Errorf("failed to write cosign vulnerability predicate: %w", err) } return nil }