# Upgrading to DefectDojo Version 3.1.x

## Blank Finding components normalized to NULL

Previously a Finding could store an empty string (`""`) for `component_name` or `component_version` depending on how it was created or edited. The database treats an empty string as distinct from `NULL`, so the **All Components** view (which groups findings by component) could show two separate “None” rows — one for findings with a `NULL` component and one for findings with an empty-string component.

Findings without a component now consistently store `NULL`. Blank values are normalized to `NULL` when a Finding is saved, and a data migration converts existing empty-string component values to `NULL` on upgrade.

### What you need to do

Nothing — the change is applied automatically by the database migration included in this release. After upgrading, component-less findings will group together under a single “None” entry.

## Multiple JIRA components per project

The `Component` field on a JIRA project configuration now supports assigning more than one Jira component. Separate multiple component names with a comma (for example, `Security,DevSecOps`), and each name is sent to Jira as a distinct component. A single value without commas continues to behave as before.

### What you need to do

Nothing is required. Note that a component name that legitimately contains a comma will be split into separate components — component names rarely contain commas, so this is an accepted limitation.

## Tool Configuration credentials upgraded to AES-256-GCM

DefectDojo encrypts the credentials stored on Tool Configurations (the `password`, `ssh`, and `api_key` fields). Previously these values were encrypted with AES-256 in OFB mode (the `AES.1` stored format). This release introduces a modern `AES.2` format that uses AES-256-GCM, an authenticated encryption scheme that detects tampering with the stored ciphertext.

New and updated credentials are written in the `AES.2` format automatically. The encryption key is unchanged — both formats derive their key from the same `DD_CREDENTIAL_AES_256_KEY`, so no key rotation or settings change is required.

A data migration (`0272_reencrypt_tool_config_credentials_aes_gcm`) included in this release eagerly re-encrypts every existing `AES.1` credential to `AES.2` on upgrade. The legacy `AES.1` decryption path is retained for backward compatibility, so any value that has not yet been migrated continues to decrypt normally. The same migration also widens the `password`, `ssh`, and `api_key` columns by 50% so that credentials stored at the old maximum length still fit once the GCM nonce and authentication tag are added.

This release also bumps `cryptography` to 49.0.0 and `pyopenssl` to 26.3.0.

### What you need to do

Nothing — the change is applied automatically by the database migration included in this release. Ensure your `DD_CREDENTIAL_AES_256_KEY` is unchanged from your prior deployment so the existing credentials can be decrypted and re-encrypted; a value that fails to decrypt (for example, because it was encrypted under a different key) is left untouched rather than overwritten.

## JFrog Xray API Summary Artifact parser: deterministic impact paths

The JFrog Xray API Summary Artifact parser derives a finding’s `file_path`, description, and `unique_id_from_tool` (its deduplication key) from the first entry in the vulnerability’s `impact_path` list. JFrog returns that list in an arbitrary order, so the same vulnerability could produce a different first entry from one scan to the next. When the order changed, the deduplication key changed too, and a single CVE would be re-imported as multiple separate findings across successive scans.

The parser now sorts the impact paths before selecting the first one, so `file_path`, the description, and the deduplication key stay stable across re-imports. When a vulnerability has more than one impact path, the full sorted list is now appended to the finding description under an **Impact paths:** heading so no path information is lost.

### What you need to do

Nothing is required for new imports. Findings imported before this release may have been created with a non-deterministic first impact path; re-importing an affected report will now deduplicate consistently, and you may want to clean up any duplicate findings that a previous import created.

## New setting: `DD_OS_MESSAGE_ENABLED`

This release adds the `DD_OS_MESSAGE_ENABLED` setting (default `True`), which controls the open-source promotional (“Upgrade to Pro”) banner. The default preserves the existing behavior. Set `DD_OS_MESSAGE_ENABLED=False` to hide the banner; when disabled, DefectDojo skips the outbound request that fetches the message.

## Deduplication execution mode for import/reimport

This release adds a new `deduplication_execution_mode` setting that controls how import/reimport deduplication post-processing is dispatched and whether the API response waits for it. It can be set per user (profile) and overridden per request on the import and reimport endpoints.

Modes:

- `async` (default): deduplication and the rest of post-processing are dispatched to the background and the response returns immediately. This is the historical behavior; nothing changes for existing users.
- `async_wait`: post-processing is still dispatched to the background, but the request waits for deduplication to finish before responding. As a result the `scan_added` notification and the statistics in the import/reimport response reflect the deduplicated state (findings that turned out to be duplicates are no longer counted/listed as new). JIRA push, product grading and other non-deduplication tasks remain asynchronous and are not awaited.
- `sync`: import deduplication runs inline in the web request.

The wait in `async_wait` is bounded by the new `DD_DEDUPLICATION_ASYNC_WAIT_TIMEOUT` environment variable (default `60` seconds). If no worker picks up the work within the timeout, the request responds anyway (degrading to the `async` outcome) rather than hanging.

The import/reimport response now also includes a `deduplication_complete` boolean indicating whether deduplication had finished by the time the response was produced.

### Relationship to `block_execution`

The existing `block_execution` profile flag is unchanged. It remains the global switch that forces **all** of a user’s asynchronous tasks (notifications, JIRA push, product grading, deduplication, …) to run in the foreground. `deduplication_execution_mode` is independent and narrower — it only affects import/reimport deduplication post-processing. A user who has `block_execution` enabled continues to get fully synchronous imports; the upgrade migration seeds their `deduplication_execution_mode` to `sync` so behavior is unchanged.
