Upgrading to DefectDojo Version 3.2.x

Vulnerability id type

Each Vulnerability_Id gains an autodetected vulnerability_id_type — the identifier’s leading prefix (CVE-2024-1234 → CVE, GHSA-… → GHSA, RUSTSEC-… → RUSTSEC). It is derived structurally (no registry) and stored (indexed) so identifiers can be filtered and grouped by type efficiently. It is NULL when there is no non-numeric prefix. It is populated automatically on import and on save(); existing rows are backfilled by migration. It does not participate in hash_code, so existing hash codes and deduplication are unaffected.

A unique constraint is also added on (finding, vulnerability_id); pre-existing duplicate rows (unintended) are consolidated first.

Multiple CWEs per finding

A finding could previously store only one CWE (the integer cwe field). This release adds a dedicated Finding_CWE relationship so a finding can carry multiple CWEs, using the same approach as vulnerability ids: the primary CWE stays on Finding.cwe (unchanged — legacy deduplication and hash codes still use it), and additional CWEs live in the relationship.

CWE is modeled separately from vulnerability identifiers on purpose: a CWE is a weakness class, not a vulnerability instance identifier, so it must not participate in hash_code, vulnerability-id deduplication, or the cve field. Because of this separation, existing hash codes and deduplication are unaffected.

CWEs are populated automatically on import and when a finding is created or edited (from the finding’s CWE field, plus any additional CWEs a parser supplies). The finding exposes them via finding.cwes (primary first, deduplicated).

Database migration

Five migrations run automatically on upgrade:

  • 0281_vulnerability_id_type — adds the indexed vulnerability_id_type column and a leading index on vulnerability_id.
  • 0282_backfill_vulnerability_id_type — backfills vulnerability_id_type and removes duplicate (finding, vulnerability_id) rows (keeping the earliest).
  • 0283_unique_finding_vulnerability_id — adds the unique constraint on (finding, vulnerability_id).
  • 0284_finding_cwe — creates the Finding_CWE table (unique per (finding, cwe)).
  • 0285_backfill_finding_cwe — seeds Finding_CWE rows for all existing findings from their legacy Finding.cwe values.

What you need to do

Nothing — the migrations are applied automatically, 0285_backfill_finding_cwe backfills every existing finding, and new/edited findings populate their CWE relationship on save and import.

The manage.py migrate_cwe management command is optional and is not required on upgrade (it would repeat the work 0285 already did). It exists only as an idempotent re-scan you can run later — for example after a parser upgrade changes how a scan’s CWEs are derived — to reconcile Finding_CWE rows from the current Finding.cwe values.

Deduplication registration repairs (changes hash_code for four scan types)

Unlike the two changes above, this one does change stored hash codes. Four scan types had a deduplication registration that was split across the two settings that have to agree, so the configured behaviour never took effect.

Burp Suite DAST Scan

Burp Suite DAST Scan is the renamed Burp Enterprise Scan — the same parser (dojo/tools/burp_suite_dast) still answers to both names. DEDUPLICATION_ALGORITHM_PER_PARSER was updated to the new name, but in HASHCODE_FIELDS_PER_SCANNER the new entry was keyed "Burp Suite DAST" (no trailing Scan) — a name no parser produces. Because HASHCODE_FIELDS_PER_SCANNER is looked up by test type name, that list never matched anything, and Burp Suite DAST Scan fell through to the legacy hash (title + cwe + line + file_path + description).

The result was that the same tool had two different identities depending on which of its two scan type names you imported under: Burp Enterprise Scan hashed on title + severity + cwe as intended, and Burp Suite DAST Scan did not.

The key is now "Burp Suite DAST Scan", so both names hash identically.

Existing Burp Suite DAST Scan findings will not match a new import until they are rehashed. Reimporting before rehashing closes the existing findings as absent and creates duplicates.

Snyk Code Scan, Cycognito Scan, n0s1 Scanner

These three carried a curated HASHCODE_FIELDS_PER_SCANNER list but had no DEDUPLICATION_ALGORITHM_PER_PARSER entry, so they deduplicated with the legacy algorithm, which does not consult hash_code at all. Their stored hash_code was already computed from the configured fields — compute_hash_code() reads the field list regardless of the algorithm — so their hash codes do not change. Only which findings match changes, and they now match on the fields their registration always specified.

What you need to do

If you import Burp Suite DAST Scan, recompute its hash codes before your next reimport:

./manage.py dedupe --parser "Burp Suite DAST Scan" --hash_code_only

Then, to re-link findings under the new identity:

./manage.py dedupe --parser "Burp Suite DAST Scan" --dedupe_only

Nothing is required for Snyk Code Scan, Cycognito Scan, or n0s1 Scanner, and nothing is required for any other scan type.

AWS Security Hub parser: deterministic resource IDs

The AWS Security Hub parser lists the resources a finding applies to in the finding description, under a Resource IDs: heading. It built that list by joining an unordered Python set. Python randomizes string hashing per process, so the resource ARNs came out in a different order in every import — and for a finding that reports more than one resource, that made the description itself different each time.

The description matters here because “AWS Security Hub Scan” declares no entry in HASHCODE_FIELDS_PER_SCANNER, so its findings fall back to the legacy hash, which is computed over title, CWE, line, file path and description. Re-importing the same unchanged report therefore stored a different hash_code every time.

The parser now sorts the resource ARNs before joining them, so the description — and the hash_code derived from it — are stable across re-imports. The Test description (AWS Accounts and Finding Origins) was built the same way and is now sorted too; it is not hashed, but it reshuffled in the UI on every import.

What you need to do

Nothing is required, but note that this is an identity change for AWS Security Hub Scan.

It affects only findings that carry two or more resources. A finding with zero or one resource has just one possible ordering, so its hash_code is unchanged by this release.

For the multi-resource findings there is no stable prior identity to preserve: the old value was effectively random per import, so no existing hash_code can be matched reliably. Every hash this changes was already changing on its own.

Deduplication for this scan type keys on unique_id_from_tool (the Security Hub finding ARN) rather than on hash_code, so import and re-import matching itself was never affected. The exposure is the features that read hash_code: false positive history, risk acceptance copies, and similar findings.

Yarn Audit parser: deterministic tree versions and dependents

The Yarn Audit parser (Yarn 2 output) joined unordered sets into the finding description and into component_version, so the listed dependents and tree versions reshuffled between imports. Both are now sorted.

This is not an identity change: “Yarn Audit Scan” declares its own hash fields (title, severity, file path, vulnerability IDs, CWE), and neither the description nor component_version is among them, so no hash_code changes. The only difference is that the values stop flapping in the UI.

Deprecation: API-based (pull) parsers

The following API-based (pull) parsers — which fetch findings directly from a vendor API using a Tool Configuration and a Product API Scan Configuration, rather than parsing an uploaded report file — are being deprecated and will be removed in DefectDojo 3.5.0 (November 2026). These pull integrations are being consolidated into DefectDojo Pro’s no-code connectors.

  • BlackDuck API
  • Bugcrowd API Import
  • Cobalt.io API Import
  • Edgescan Scan
  • SonarQube API Import
  • Vulners

What you need to do

If you use any of these parsers to pull findings directly from a vendor API, plan to migrate to a DefectDojo Pro connector before 3.5.0. After 3.5.0, these parsers and their API-pull import path are removed, and imports that rely on a Tool Configuration will no longer function.

Deprecation: Tool Type and Tool Configuration

The Tool Type and Tool Configuration features exist to configure the API-based pull parsers listed above. They are being deprecated and will be removed in DefectDojo 3.5.0 (November 2026), at the same time as the parsers they serve, so that no configuration tables remain that do nothing. (CI/CD engagement data entry no longer depends on Tool Configuration as of the CI/CD infrastructure split in this release.)

The following UI pages and API endpoints are affected:

  • UI: Tool Type, Tool Configuration, and per-product API Scan Configuration pages
  • API: /api/v2/tool_types/, /api/v2/tool_configurations/, /api/v2/product_api_scan_configurations/

What you need to do

If you manage Tool Types or Tool Configurations via the UI or API, migrate the corresponding integrations to DefectDojo Pro connectors before 3.5.0. From 3.2.0 onward these pages display a deprecation warning and the API endpoints return an X-Deprecated response header.

Deprecation: manage.py dbbackup

The bundled django-dbbackup integration (the manage.py dbbackup / dbrestore commands) is being deprecated and will be removed in DefectDojo 3.5.0 (November 2026). It is minimally integrated, and its pg_dump-based backup fails when the PostgreSQL client and server versions differ (see #15301).

What you need to do

For database backups, use your database’s native tooling — for example pg_dump/pg_restore matched to your PostgreSQL server version, or your managed database provider’s backup features.

Deprecation timeline

  • 3.2.x onwards: the features above are deprecated. UI pages display a warning banner and affected API endpoints return an X-Deprecated header. In DefectDojo Pro, the sidebar entries for Tool Types and Tool Configurations also carry a red DEPRECATED badge naming the removal release and linking back to this page — see Menu Badges.
  • 3.5.0 (November 2026): the API-based pull parsers, Tool Type / Tool Configuration, and the django-dbbackup integration are removed.

For more information, check the Release Notes.