Trivy Integration with DefectDojo
Trivy Integration with DefectDojo
Trivy is an open source security scanner maintained by Aqua Security. A single binary scans container images, filesystems, Git repositories, virtual machine images, and Kubernetes clusters, and reports known vulnerabilities in OS and language packages, infrastructure as code misconfigurations, exposed secrets, and software licenses. Trivy Operator, also from Aqua, runs Trivy inside a Kubernetes cluster and stores results as custom resources such as VulnerabilityReport, ConfigAuditReport, and ExposedSecretReport. Both write JSON, and DefectDojo has a parser for each.
Trivy Integration with DefectDojo
Trivy is the scanner we run everywhere: in every image build, against Terraform in pull requests, and continuously in our clusters through Trivy Operator. That breadth is also why its output needs a home. Imported into DefectDojo, each CVE, misconfiguration, and secret becomes a Finding on the Asset that owns the image or workload, deduplicated across builds, with an SLA and an owner. Trivy's vendor status for each CVE comes along, so a vulnerability the distribution says doesn't affect us arrives already mitigated.
Why Trivy Matters
Container and cloud-native environments create many places for vulnerabilities to hide, and Trivy covers most of them with one tool.
- It finds CVEs in OS packages and in language dependencies inside images, including ones the application team never declared directly.
- The same binary checks Dockerfiles, Kubernetes manifests, Terraform, and other IaC for misconfigurations.
- Secret scanning catches credentials baked into image layers or committed to repositories.
- Trivy Operator rescans workloads in the cluster, so newly published CVEs are caught in images that are already running.
- Each scan is a snapshot. Knowing which CVEs are new this week, or which team owns them, needs a system that keeps history.
Advantages of This Integration
What we gained by running Trivy through DefectDojo:
- Deduplication across builds. Trivy Scan findings are hashed on title, severity, vulnerability IDs, CWE, and description; Trivy Operator findings on title, severity, vulnerability IDs, and description. Rescanning an unchanged image doesn't create new findings.
- Vendor status mapped to DefectDojo status. A Trivy status of
not_affectedarrives inactive, verified, and mitigated;unknownandunder_investigationarrive unverified; affected and fix-pending statuses stay active and verified. - Fix availability. Findings record whether a fixed version exists, which lets teams separate "upgrade now" from "wait for the vendor."
- Lifecycle through reimport. Reimporting each build's report into the same Test closes CVEs a base image update removed and reopens any that return.
- Kubernetes context. Cluster scans and Trivy Operator reports record namespace, kind, and workload name as the finding's service, so the same CVE in two deployments is tracked separately.
How This Integration Works
There are two scan types: Trivy Scan for Trivy CLI JSON and Trivy Operator Scan for Trivy Operator custom resources.
Trivy Scan. Run Trivy with JSON output, for an image or for a cluster:
trivy image --format json --output trivy-image.json registry.example.com/orders:2.3.1
trivy k8s --report all --format json --output trivy-k8s.json
The parser accepts the current report schema (SchemaVersion 2), the older list-style format, and Kubernetes cluster reports. Filesystem, repository, and config scans use the same schema. Import in the UI with Import Scan Results, or with the API in Community Edition or DefectDojo Pro:
curl "https://YOUR_INSTANCE/api/v2/import-scan/" \
-H "Authorization: Token $DD_API_TOKEN" \
-F "scan_type=Trivy Scan" \
-F "file=@trivy-image.json" \
-F "product_name=orders" \
-F "engagement_name=Image Builds" \
-F "auto_create_context=true"
DefectDojo Pro users can run the same import with Universal Importer:
universal-importer import \
--defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/" \
--scan-type "Trivy Scan" \
--report-path "./trivy-image.json" \
--product-name "orders" \
--engagement-name "Image Builds" \
--auto-create-context
Trivy Operator Scan. Export the operator's reports from the cluster as JSON. The parser accepts a single report object, a JSON array of reports, or a dictionary keyed by resource type (for example vulnerabilityreports.aquasecurity.github.io). For a whole namespace, extract the items array from the list:
kubectl get vulnerabilityreports -n payments -o json | jq '.items' > trivy-operator.json
Import it with scan_type=Trivy Operator Scan using the same API or Universal Importer commands. The DefectDojo docs also point to the community trivy-dojo-report-operator project, which pushes VulnerabilityReports to DefectDojo automatically.
Data Granularity: What Gets Imported
Trivy Scan
| DefectDojo Field | Source in Trivy JSON | Notes |
|---|---|---|
| Title (vulnerabilities) | VulnerabilityID, PkgName, InstalledVersion |
For example CVE-ID package version |
| Severity | Severity |
UNKNOWN is Info; if missing, derived from CVSS (preferring the severity source, then nvd, ghsa, redhat, bitnami) |
| CVSS v3 / v4 | CVSS vectors and scores |
|
| Description | Title, target, type, fixed version, description | |
| Mitigation / Fix Available | FixedVersion |
Fix available is false when empty |
| Impact / Status | Status |
Drives active, verified, and mitigated flags |
| CWE | CweIDs |
First as primary; full list stored |
| Component / File Path | Package name and version; PkgPath or Target |
|
| Misconfigurations | ID, Title, Resolution, PrimaryURL, CauseMetadata |
Title ID - Title; offending lines added to description |
| Secrets | Title, Category, Match, StartLine |
Title Secret detected in target - title |
| Licenses | Name, Category, PkgName, Confidence |
Title License detected in target - name |
| Tags / Service | Target type and class; cluster namespace, kind, name | |
| Finding type | Static |
Trivy Operator Scan
| DefectDojo Field | Source in Operator Report | Notes |
|---|---|---|
| Vulnerabilities | report.vulnerabilities |
Title vulnID package version; score stored as CVSS v3 score; publish date kept |
| Config and RBAC checks | report.checks |
Title checkID - title; remediation and messages as mitigation |
| Secrets | report.secrets |
Title Secret detected in target - title |
| Compliance | status.detailReport, status.summaryReport |
Failed CIS-style checks and cluster compliance controls; marked dynamic |
| Service | Resource namespace, kind, name, container | From report labels |
| Tags | Namespace, package type, class, check category | |
| Vulnerability IDs | CVE or normalized AVD check ID |
SBOM reports in the operator output are ignored.
Use Cases
Image builds in CI: Every build runs trivy image and reimports into a Test for that image. Engineers see only the change from the previous build, and a release step can check DefectDojo for new Critical findings with a fix available.
Cluster-wide visibility: Trivy Operator keeps reports for running workloads in the cluster. A scheduled export reimports the reports so newly disclosed CVEs in already-deployed images become findings with owners, tagged by namespace.
IaC review: Trivy config scans of Terraform and Kubernetes manifests import as misconfiguration findings with the offending lines in the description, alongside the image CVEs for the same service.
Compliance evidence: Failed checks from Trivy Operator compliance reports are tracked as findings, so remediation of benchmark failures has the same history and SLAs as other work.
Operational Tips
- Use one Test per image or per namespace and reimport into it. Mixing many images in one Test makes reimport close findings that still exist elsewhere.
- Decide how to handle vendor statuses.
will_not_fix,fix_deferred, andend_of_lifestay active, so risk-accept them with an expiry rather than letting them age out of SLA. - Filter at the source if you want to. Trivy's own
--ignore-unfixedand severity flags reduce what gets imported, andminimum_severitydoes the same on the DefectDojo side. - Treat secret findings as sensitive. The
Matchtext is copied into the description, so restrict access to those Tests. - Tag imports with the image name and tag (for example
tags=orders,2.3.1) so findings can be filtered by release. - Prefer CLI JSON for build-time results and Trivy Operator exports for what is running. Keeping them in separate Engagements shows the gap between what was built and what is deployed.