Skip to content

Trivy Operator Scan parser embeds volatile ReplicaSet name into service, permanently breaking close_old_findings #16026

Description

@tallesgois-shipay

Bug description

The bundled "Trivy Operator Scan" parser builds Finding.service from the scanned resource's identity, including the Kubernetes object name:

service = f"{resource_namespace}/{resource_kind}/{resource_name}"
service = f"{service}/{container_name}"

(dojo/tools/trivy_operator/vulnerability_handler.py)

When the scanned resource is a Deployment-managed Pod, resource_name is the ReplicaSet name, which changes on every deploy (new hash suffix). Since close_old_findings scopes its query by exact service match:

if self.service is not None:
    old_findings = old_findings.filter(service=self.service)
else:
    old_findings = old_findings.filter(Q(service__isnull=True) | Q(service__exact=""))

(dojo/importers/default_importer.py)

...every reimport after a new deploy uses a brand-new service value, so close_old_findings can never see (and therefore never close) findings created by any previous deploy generation. Findings only ever accumulate; nothing is ever mitigated by reimport for this scan type, regardless of close_old_findings=true.

This is the same underlying pattern already discussed in #11500, where a maintainer clarified that service is meant to be a stable identifier chosen by the caller, and reimports will only close old findings correctly "as long as you don't include a version number and the value stays the same across reimports." That guidance is correct for callers building their own service value via the API — but here the violation is happening inside DefectDojo's own bundled parser, not in caller-supplied input. Nothing in the trivy-dojo-report-operator integration (or any other caller of /api/v2/reimport-scan/ for this scan type) has the ability to override this, since the parser derives and sets service itself from the report content.

Impact observed in production

Over ~3 months, one dojo_finding table grew from ~218k to 5.7M+ rows for Kubernetes workloads scanned via Trivy Operator across 8 clusters, because no finding from a prior deploy generation was ever closed automatically — only ever added to. This directly degraded Postgres performance (large table + index footprint) enough to cause dashboard timeouts and an availability incident, on top of requiring recurring manual SQL cleanup as a workaround.

Steps to reproduce

  1. Deploy a workload managed by a Deployment (so its Pods belong to a ReplicaSet) in Kubernetes.
  2. Scan it with the Trivy Operator and reimport the VulnerabilityReport into DefectDojo via /api/v2/reimport-scan/ with scan_type=Trivy Operator Scan, close_old_findings=true.
  3. Trigger a new deploy (new ReplicaSet, e.g. any rolling update) and reimport the new scan for the same workload/engagement.
  4. Observe: findings from the first scan remain active, even for CVEs no longer present in the new scan / already fixed. Finding.service differs between the two Tests (different ReplicaSet name embedded).

Expected behavior

close_old_findings should be able to recognize that both reimports are for the same logical Kubernetes workload, and close findings that are genuinely no longer present. At minimum, the bundled Trivy Operator parser should not embed a value that's expected to change on every reimport (ReplicaSet name) into a field (service) whose entire purpose is to stay stable across reimports.

Suggested fixes (any of)

  • Drop resource_name (or just the ReplicaSet-generated suffix) from the service string built in vulnerability_handler.py, keeping only namespace/kind/container (or similar stable identity).
  • Expose this as a configurable behavior for the Trivy Operator parser, similar to how DD_HASHCODE_FIELDS_PER_SCANNER lets users override deduplication hash fields per parser (see trivy operator scan: deduplication is not working #12320) — but for service construction.
  • Document, in the same place service's stability requirement is documented (per the discussion in Issue with closing of old findings for upgraded image #11500), that scanner parsers bundled with DefectDojo are also expected to honor this contract, since users have no way to override parser-internal service construction today.

Deployment method

  • Kubernetes (Helm)

Environment information

  • DefectDojo version: 2.58.4
  • Integration: telekom-mms/trivy-dojo-report-operator → /api/v2/reimport-scan/, scan_type=Trivy Operator Scan

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions