Skip to content

feat: add Fingerprint field to vulnerability results for consistent identification #9793

Description

@knqyf263

Description

Add a Fingerprint field to vulnerability results to provide a consistent and unique identifier for each vulnerability. This enables external systems (security management platforms, issue trackers, databases, etc.) to reliably deduplicate and track vulnerabilities across multiple scans.

Background

When integrating Trivy with external security management systems, there's a need for a stable identifier to:

  • Deduplicate the same vulnerability across multiple scan runs
  • Track vulnerability lifecycle (detection, suppression, remediation)
  • Maintain persistent dismissals/suppressions across scans
  • Link vulnerabilities to external ticketing systems
  • Build historical trend analysis

Currently, external systems must generate their own identifiers by combining various fields, which leads to inconsistency across different tools and platforms.

Requirements

The fingerprint should provide the following characteristics:

  1. Same Artifact + Same Target + Same Package → Same Fingerprint

    • If a vulnerability is detected in the same artifact, same target (file path), and same package, it should produce the same fingerprint
  2. Different Artifacts → Different Fingerprints

    • Example: alpine:3.20 and alpine:3.21 both detect CVE-2025-0001 in the same package, but their fingerprints must differ
  3. Different Targets (file paths) → Different Fingerprints

    • Example: app1/package-lock.json and app2/package-lock.json both contain the same vulnerable package with the same CVE, but their fingerprints must differ
    • This allows proper tracking of vulnerabilities in monorepos or multi-project containers
  4. Different Packages → Different Fingerprints

    • Example: package-a and package-b both affected by CVE-2025-0001 must have different fingerprints
  5. Different Package Versions → Different Fingerprints

    • Example: Within the same project, if package-a@v1.0.0 and package-a@v2.0.0 are both affected by CVE-2025-0001, their fingerprints should be different

Proposed Implementation

Add a Fingerprint field to the DetectedVulnerability struct (in pkg/types/result.go):

type DetectedVulnerability struct {
    // ... existing fields ...
    Fingerprint string `json:",omitempty"`
}

The fingerprint should be generated from a combination of:

  • ArtifactID (from Report, introduced in feat: add ArtifactID field to uniquely identify scan targets #9663) - uniquely identifies the scan target/artifact
  • Target (from Result) - identifies the file/path within the artifact (e.g., app1/package-lock.json, app2/package-lock.json)
  • PkgID - package identifier (includes name, version, and other package-specific identifiers)
  • VulnerabilityID - CVE/vulnerability identifier

Example fingerprint generation:

data := fmt.Sprintf("%s:%s:%s:%s",
    report.ArtifactID,
    result.Target,
    vuln.PkgID,
    vuln.VulnerabilityID)
hash := sha256.Sum256([]byte(data))
fingerprint := fmt.Sprintf("%x", hash)

Benefits

  • Consistency: All external tools use the same identifier for the same vulnerability
  • Interoperability: Easy integration with various security platforms and databases
  • Simplified tracking: External systems don't need to implement their own fingerprinting logic
  • Reliability: Based on stable fields that uniquely identify vulnerabilities
  • Monorepo support: Properly distinguishes vulnerabilities across different projects within the same artifact

Related Work

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/featureCategorizes issue or PR as related to a new feature.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions