GitLab Integration with DefectDojo
GitLab Integration with DefectDojo
GitLab is a DevSecOps platform from GitLab Inc. that combines source control, CI/CD, and a set of built-in security analyzers. Those analyzers run as pipeline jobs and write JSON reports that follow GitLab's published security report schemas: SAST, Dependency Scanning, Container Scanning, Secret Detection, DAST, and API Fuzzing. Which analyzers are available depends on your GitLab tier and how your pipelines are configured. DefectDojo has a parser for each of the six report types, and DefectDojo Pro adds a GitLab connector for Assets and issue tracking.
GitLab Integration with DefectDojo
Our code and pipelines already live in GitLab, so its security jobs were the easiest scanners to turn on. The problem came later: six report types per project, spread across hundreds of pipelines, with no shared place to triage them or see the trend. Sending every GitLab security report to DefectDojo gives each project's findings an Asset, deduplicates them across pipeline runs, and puts them next to results from the scanners GitLab doesn't run for us. Developers keep working in GitLab, and the security team gets one queue with SLAs and history.
Why GitLab Matters
GitLab's analyzers sit where code is written and merged, which makes them one of the cheapest places to catch problems.
- One platform covers code (SAST), dependencies, container images, committed secrets, running applications (DAST), and API endpoints (API Fuzzing).
- All six reports share a JSON schema family, with stable vulnerability IDs, identifiers such as CVE and CWE, and suggested solutions.
- The jobs run on every pipeline, so results stay current with the code instead of trailing it by a quarter.
- Pipeline results are scoped to one project and one run. Comparing across projects, tracking fixes over months, or applying SLAs needs something outside the pipeline.
Advantages of This Integration
What we gained by running GitLab security reports through DefectDojo:
- One queue for six report types. SAST, dependency, container, secret, DAST, and API Fuzzing findings land on the same Asset, filterable by Test.
- Deduplication tuned per report type. Dependency findings are hashed on title, vulnerability IDs, file path, component name, and component version. The other report types use DefectDojo's default identity of title, CWE, line, file path, and description.
- Lifecycle across pipeline runs. Reimporting each run's report into the same Test mitigates what was fixed, adds what is new, and reactivates regressions.
- SLAs and severity normalization. For most report types, GitLab's Unknown severity becomes Info (SAST and Dependency Scanning also handle Undefined and keep the original label in the title), so findings fit DefectDojo's Critical through Info SLA scale.
- DefectDojo Pro connector. The GitLab connector creates Assets from your GitLab projects, and its downstream side can open GitLab issues from DefectDojo findings.
How This Integration Works
Each GitLab report type has its own scan type in DefectDojo. Use the exact names below:
- GitLab SAST Report for
gl-sast-report.json - GitLab Dependency Scanning Report for
gl-dependency-scanning-report.json - GitLab Container Scan for
gl-container-scanning-report.json - GitLab Secret Detection Report for
gl-secret-detection-report.json - GitLab DAST Report for
gl-dast-report.json - GitLab API Fuzzing Report Scan for the API Fuzzing JSON report
1. Collect the report. Each analyzer job saves its JSON file as a pipeline artifact. Pick it up in a later job of the same pipeline, or download the job artifact from GitLab.
2. Import it. In the UI, open the Engagement, choose Import Scan Results, select the matching GitLab scan type, and upload the file. From a pipeline, call the API (Community Edition and DefectDojo Pro):
curl "https://YOUR_INSTANCE/api/v2/import-scan/" \
-H "Authorization: Token $DD_API_TOKEN" \
-F "scan_type=GitLab SAST Report" \
-F "file=@gl-sast-report.json" \
-F "product_name=payments-api" \
-F "engagement_name=GitLab CI" \
-F "test_title=GitLab SAST" \
-F "auto_create_context=true"
DefectDojo Pro users can use Universal Importer instead:
universal-importer import \
--defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/" \
--scan-type "GitLab Dependency Scanning Report" \
--report-path "./gl-dependency-scanning-report.json" \
--product-name "payments-api" \
--engagement-name "GitLab CI" \
--auto-create-context
Repeat per report type, one Test each. On later pipeline runs, send each report to /api/v2/reimport-scan/ against its existing Test so a reimport of one report type never touches findings from another.
3. Connect GitLab in DefectDojo Pro (optional). The GitLab connector has two sides:
- Upstream (Asset connector). With a Personal Access Token that has the
read_apiscope, it lists every project the token can access and creates a Record for each, grouped into Organizations by namespace. It imports no findings. An Exclude Archived Projects toggle leaves archived projects out. - Downstream. With a token that has API scopes and a target project, DefectDojo pushes findings to GitLab as issues, manually or automatically per Asset or Engagement. Severity maps to Priority (Info 1 through Critical 5), and Active maps to opened while Closed, False Positive, and Risk Accepted map to closed.
Data Granularity: What Gets Imported
| DefectDojo Field | Source in GitLab Report | Notes |
|---|---|---|
| Title | name, or message |
Dependency titles are prefixed with the CVE. Container titles fall back to "CVE in package-version". Secret titles get a revoke reminder appended |
| Severity | severity |
Unknown becomes Info. SAST and Dependency also map Undefined and note the original in the title. DAST passes severity through unchanged |
| Description | Scanner name, message, description |
Secret Detection appends the raw source extract. API Fuzzing uses category, crash type, and crash state |
| Mitigation | solution |
All except Secret Detection and API Fuzzing |
| References | Non-CVE/CWE identifiers, or links |
Identifiers for SAST and Dependency. Link URLs for DAST |
| CVE / CWE | identifiers |
CVE for SAST, Dependency, Container. CWE for all but Secret Detection and API Fuzzing |
| Component | location.dependency |
Package name and version (Dependency, Container) |
| File Path / Line | location.file, start_line, end_line |
SAST, Secret Detection, and Dependency (file only). SAST records class and method as source and sink objects |
| Endpoint | location.hostname + path |
DAST only. Request and response headers are kept as evidence |
| Confidence | confidence |
SAST and DAST, mapped to DefectDojo's numeric scale |
| Unique ID | Vulnerability id |
Set for all six. Repeated IDs in one SAST or Dependency report collapse to one finding |
| Finding type | Static, or Dynamic | Dynamic for DAST and API Fuzzing, static for the rest |
| Deduplication | Hashcode or Legacy | Dependency: title, vulnerability IDs, file path, component. Others: title, CWE, line, file path, description |
DAST reports that list the same issue at several URLs are merged into one finding with an occurrence count and every endpoint attached. DAST and API Fuzzing have no dedicated deduplication algorithm entry, so Community Edition falls back to the Legacy algorithm for them.
Use Cases
In every merge request pipeline: A job after the security stage reimports each GitLab report into its own Test on the project's Asset. A release gate checks DefectDojo for new High or Critical findings, while findings that were risk-accepted last month stay out of the way.
Across a large GitLab group: With DefectDojo Pro, the upstream connector creates an Asset for every project in a namespace. Pipelines then import into those Assets by name, and security leads report on exposure by group instead of project by project.
For leaked credentials: Secret Detection findings carry the file and line plus a reminder to revoke. Routing them to a short SLA in DefectDojo makes sure the rotation happens, not just the commit that removes the string.
Handing work back to developers: Teams on DefectDojo Pro push triaged findings to GitLab issues through the downstream connector, so remediation shows up in the project's own backlog with a priority set from severity.
Operational Tips
- Name Tests by report type (for example
test_title=GitLab Container Scan) and reimport into them on each pipeline. Mixing report types in one Test causes reimport to mitigate the wrong findings. - Use
close_old_findingswith care on the default branch only. Feature branch pipelines with partial scans can otherwise close findings that still exist on main. - Watch for titles beginning with "[Unknown severity]" or "[Undefined severity]". They imported as Info and may need a manual severity before SLAs mean anything.
- Dependency findings for the same CVE in different lockfiles stay separate, because file path and component name and version are part of their identity. That matches how the fix gets made: one lockfile at a time.
- Set
minimum_severity=Lowif Info results from DAST or API Fuzzing crowd the queue. - On DefectDojo Pro, set up the upstream connector before wiring pipelines, so imports land in Assets that already match your GitLab project structure.