Without a unified system, vulnerabilities multiply: what to do?
Imagine: your company uses Trivy, Snyk, OWASP ZAP, and Checkmarx — five different scanners, each with its own interface. Without a unified vulnerability management system, engineers spend up to 40 hours per month on manual triage, coordination, and reporting. The result: critical issues are missed, and low-priority vulnerabilities pile up. According to CISA, more than 50% of attacks exploit known vulnerabilities from KEV — confirming the need for automation. Per DefectDojo's official documentation, the platform supports over 100 scanner types. Our engineers (holding AWS, CKS, CISSP certifications) deploy DefectDojo and Dependency-Track to automate aggregation, deduplication, and prioritization. The outcome is 80% time savings and MTTR reduction to 24 hours for P1 incidents. Over the years, we have completed dozens of VM projects, reducing manual analysis by an average of 5x.
Tool selection and architecture
Three primary approaches:
- DefectDojo — open source platform. Accepts results from 100+ scanners (Trivy, Snyk, Checkmarx, ZAP, Burp), deduplicates by CPE/CVE, groups by products and teams, allows SLA assignment and Jira synchronization.
- Dependency-Track — specialized for SCA and SBOM. Receives CycloneDX/SPDX reports, continuously cross-references components with NVD, OSV, GitHub Advisories. Dashboard with time-based metrics.
- Commercial platforms (Snyk, Wiz, Tenable.io, JFrog Xray) — better integration, more expensive, less customization.
For most teams without a large security budget, the DefectDojo + Dependency-Track combination covers 80% of needs. Based on our data, this combo is 3x cheaper than Snyk Enterprise with comparable functionality.
Data flow:
CI/CD pipelines
├── Trivy (fs + image) → SARIF / JSON
├── Snyk (code + oss) → SARIF / JSON
├── GitLeaks → JSON
├── Checkmarx → SARIF
└── OWASP ZAP → JSON
│
▼
DefectDojo API (import results, deduplication)
│
├── Engagement per Product per Sprint
├── Finding deduplication by hash
├── JIRA sync (critical findings → tickets)
└── Metrics: open/closed/accepted risk DefectDojo: installation and basic setup
# Docker Compose cd django-DefectDojo ./dc-build.sh docker compose up -d # Helm in k8s helm repo add defectdojo https://raw.githubusercontent.com/DefectDojo/django-DefectDojo/helm-charts helm install defectdojo defectdojo/defectdojo \
--namespace security \
--create-namespace \
--set django.ingress.enabled=true \
--set django.ingress.host=defectdojo.internal \
--values my-values.yaml Technical implementation: from CI/CD to prioritization
How to set up automatic vulnerability import from CI/CD?
Import results via API (GitLab CI):
upload-to-defectdojo:
stage: .post
image: curlimages/curl:latest
when: always
script:
- |
ENGAGEMENT_ID=$(curl -s -X POST \
-H "Authorization: Token $DEFECTDOJO_API_TOKEN" \
-H "Content-Type: application/json" \
"$DEFECTDOJO_URL/api/v2/engagements/" \
-d "{ \"product\": $DEFECTDOJO_PRODUCT_ID, \"name\": \"CI scan - $CI_COMMIT_SHORT_SHA\", \"target_start\": \"$(date +%Y-%m-%d)\", \"target_end\": \"$(date +%Y-%m-%d)\", \"status\": \"In Progress\", \"engagement_type\": \"CI/CD\" }" | jq -r '.id')
- |
curl -s -X POST \
-H "Authorization: Token $DEFECTDOJO_API_TOKEN" \
-F "engagement=$ENGAGEMENT_ID" \
-F "scan_type=Trivy Scan" \
-F "[email protected]" \
-F "minimum_severity=High" \
-F "active=true" \
-F "verified=false" \
-F "close_old_findings=true" \
"$DEFECTDOJO_URL/api/v2/import-scan/"
- |
if [ -f zap-report.json ]; then
curl -s -X POST \
-H "Authorization: Token $DEFECTDOJO_API_TOKEN" \
-F "engagement=$ENGAGEMENT_ID" \
-F "scan_type=ZAP Scan" \
-F "[email protected]" \
-F "minimum_severity=High" \
"$DEFECTDOJO_URL/api/v2/import-scan/"
fi
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Dependency-Track: working with SBOM:
generate-and-upload-sbom:
stage: security
image: aquasec/trivy:latest
entrypoint: [""]
script:
- trivy fs --format cyclonedx --output sbom-fs.json .
- trivy image --format cyclonedx --output sbom-image.json $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- |
curl -X PUT -H "X-API-Key: $DEPENDENCY_TRACK_API_KEY" -H "Content-Type: application/json" \
"$DEPENDENCY_TRACK_URL/api/v1/bom" \
-d "{\"project\": \"$DTRACK_PROJECT_UUID\", \"bom\": \"$(base64 -w 0 sbom-image.json)\"}"
artifacts:
paths:
- sbom-*.json
expire_in: 90 days
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Why is CVSS not always sufficient?
CVSS 9.8 is a theoretical maximum risk. Real risk = CVSS × exploitability in context × asset criticality. A component with CVSS 7.5 in a public-facing API without authentication is more dangerous than a CVSS 9.8 in an offline batch service.
What is CISA KEV and how does it help prioritize vulnerabilities?
KEV (Known Exploited Vulnerabilities) from CISA lists actively exploited vulnerabilities. If a CVE is in this list, treat as P1 regardless of CVSS.
Priority system:
| Criterion | P1 (SLA: 24h) | P2 (SLA: 7d) | P3 (SLA: 30d) |
|---|---|---|---|
| CVSS | ≥ 9.0 | 7.0–8.9 | < 7.0 |
| Exploit in wild | Yes | No | No |
| Asset exposure | Public-facing | Internal | Isolated |
| Fix available | Yes | — | — |
import json, requests
def enrich_with_kev(trivy_report_path):
kev = requests.get("https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json").json()
kev_ids = {v['cveID'] for v in kev['vulnerabilities']}
with open(trivy_report_path) as f:
report = json.load(f)
for result in report.get('Results', []):
for vuln in result.get('Vulnerabilities', []):
if vuln.get('VulnerabilityID') in kev_ids:
vuln['InKEV'] = True
vuln['Priority'] = 'P1'
return report Implementation process and results
Key metrics
- MTTR by severity — average time from detection to fix
- Open Critical trend — dynamics over 30/60/90 days
- SLA compliance rate — percentage of findings closed within SLA
- Reopen rate — quality of fixes
- Suppress rate — share of accepted risk
DefectDojo builds these metrics automatically. For Grafana, export via Prometheus exporter (DefectDojo documentation available on GitHub).
Comparison of DefectDojo, Dependency-Track, and commercial platforms
| Characteristic | DefectDojo | Dependency-Track | Commercial (Snyk, Wiz) |
|---|---|---|---|
| Input type | Scan results | SBOM (CycloneDX/SPDX) | Results + SBOM |
| Deduplication | By hash, CPE, CVE | No (components only) | Automatic |
| Metrics | Built-in, API | Dashboard | Built-in |
| Scanner support | 100+ | Any generating SBOM | Limited |
| Price | Free | Free | Paid (vendor-dependent) |
Implementation process
- Audit current security stack and processes
- Deploy DefectDojo and/or Dependency-Track (Docker Compose or Helm)
- Integrate result import from CI/CD (GitLab, GitHub Actions, Jenkins)
- Configure deduplication, prioritization policies, and SLA
- Jira/GitLab sync for automatic task assignment
- Dashboards and weekly reporting
- Document architecture and scripts
- Train the team on platform usage
What's included in the work
- Audit — analysis of current scanners, report formats, triage processes
- Deployment — installation and configuration of DefectDojo/Dependency-Track in your infrastructure (Docker, k8s, bare metal)
- Integrations — CI/CD pipelines, Jira, Slack, single sign-on (SSO)
- Prioritization policies — rule setup based on your SLA and asset criticality
- Dashboards — Grafana + Prometheus exporter for metric monitoring
- Documentation — architectural diagram, runbook for operations, automation scripts
- Training — workshop for the team (2-4 hours) on platform usage
- Post-release support — 2 weeks of maintenance after implementation
Estimated timelines
An average project takes from 2 weeks (single team, simple stack) to 2-3 months (large organization, enterprise integrations). Cost is calculated individually. Savings on manual report processing — up to 40 hours per month, bringing significant cost reduction. Investment pays off within a few months. We work turnkey: from audit to post-release support.
Contact us for an assessment of your project. Request a consultation, and we will select the optimal vulnerability management architecture for your stack.







