# Upgrading to DefectDojo Version 3.0.x

## Locations enabled by default

`DD_V3_FEATURE_LOCATIONS` now defaults to `True`. Locations is a polymorphic location/asset model that replaces the legacy `Endpoint` model. **URL Locations** are the direct equivalent of Endpoints (same `protocol`, `host`, `port`, `path`, `query`, and `fragment` fields), and the model additionally supports **Dependency Locations** for SBOM/library data that Endpoints could never represent.

### How to migrate

After the feature is enabled on an existing instance, run the **`migrate_endpoints_to_locations`** management command to carry your Endpoint data forward into Locations. Enabling the flag alone does **not** move data — the command performs the one-time conversion. For every Endpoint, it:

1. Creates (or re-uses) a **URL Location** from the Endpoint’s `protocol`, `userinfo`, `host`, `port`, `path`, `query`, and `fragment`.
2. Carries over all **tags** and re-points all **metadata** (`DojoMeta`) onto the new Location.
3. Creates a **`LocationProductReference`** so the URL appears under the correct Asset (Product).
4. Creates a **`LocationFindingReference`** for every `Endpoint_Status`, collapsing the old multi-flag combinations into a single canonical status (first match wins):

| Endpoint_Status flag             | Resulting Location status |
| --------------------------------- | ------------------------- |
| `risk_accepted=True`             | **Risk Accepted**         |
| `false_positive=True`            | **False Positive**        |
| `out_of_scope=True`              | **Out of Scope**         |
| `mitigated=True`                 | **Mitigated**            |
| (none of the above)              | **Active**               |

#### Running the migration

```
python manage.py migrate_endpoints_to_locations
```

- **Idempotent — safe to re-run.** Each phase uses `bulk_create(..., ignore_conflicts=True)`, so re-running the command will not create duplicates and will pick up any Endpoints not yet converted. After converting, it runs a tag-inheritance pass so migrated Locations pick up inherited product tags.
- **Resilient to per-row failures.** A single bad Endpoint is logged (with its ID) and skipped rather than aborting the whole run; re-run after addressing the cause to convert the remainder. The command prints live progress with an ETA and a final migrated/total summary.
- **Tuning flags (optional):**`--batch-size` (DB iterator chunk size, default `1000`) and `--progress-every` (progress-line cadence, default `50`). `--benchmark` and `--query-count` exist for profiling only and add overhead.

For full details (including the read-compatibility behavior of the legacy API), see [Migrating from Endpoints](https://docs.defectdojo.com/asset_modelling/locations/pro__migrating_from_endpoints/).

### What happens to existing endpoint data

- **Nothing is deleted.** The original `Endpoint` and `Endpoint_Status` rows remain in the database to back the read-only legacy API. They are simply no longer used by the new UI or by imports.
- **Reads keep working; writes return 403.**`GET /api/v2/endpoints/` and `GET /api/v2/endpoint_status/` return rows projected from Locations, preserving the original Endpoint IDs and familiar fields. `POST`/`PUT`/`PATCH`/`DELETE` on those routes return `HTTP 403` — write clients should move to `POST /api/v2/urls/`, `POST /api/v2/location_findings/`, and `POST /api/v2/location_products/`.

### How to roll back

Set `DD_V3_FEATURE_LOCATIONS=False` to return to the legacy Endpoint model, UI, and read/write API. Because the original Endpoint rows are never deleted, your pre-upgrade endpoint data is still there.

> **Caveat — migration is one-way.** There is no automated path that re-creates Endpoints from Locations. Any endpoint changes you made through the new Location endpoints while the feature was enabled are **not** back-ported into the legacy `Endpoint` tables, so they will not be visible after rolling back.

## Asset / Organization labels enabled by default

`DD_ENABLE_V3_ORGANIZATION_ASSET_RELABEL` now defaults to `True`. This renames **“Product Type” → “Organization”** and **“Product” → “Asset”** throughout the UI, and routes `/product/type` → `/organization` and `/product` → `/asset` (with backward-compatibility redirects from the old paths).

This change is **cosmetic only**: the database model names, field names, and API endpoints are unchanged, so existing automation and integrations continue to work without modification.

### How to roll back

Set `DD_ENABLE_V3_ORGANIZATION_ASSET_RELABEL=False` to restore the “Product” / “Product Type” labels and the original URLs. No data is changed by this feature, so the rollback is fully reversible.

## Authorized Users panel replaces Members/Groups under legacy authorization

Open Source DefectDojo uses the legacy authorization model: access to a Product is granted by `Product.authorized_users` (with cascade via `Product_Type.authorized_users`), and `is_staff` / `is_superuser` bypass everything.

In 2.59 the classic UI restores the **“Authorized Users”** panel on the Product and Product Type detail pages. The panel reads from and writes to `Product.authorized_users` / `Product_Type.authorized_users` directly, so adding a user actually grants them the access the UI suggests it does.

### New endpoints

- `GET/POST /product/<pid>/authorized_users/add` — list / add users to `Product.authorized_users`
- `POST /product/<pid>/authorized_users/<user_id>/delete` — remove a user
- `GET/POST /product/type/<ptid>/authorized_users/add` — same for `Product_Type.authorized_users`
- `POST /product/type/<ptid>/authorized_users/<user_id>/delete`

Both endpoints are gated so only `is_staff` / `is_superuser` users can add or remove. Non-staff users see the panel but no management actions.

### How RBAC rows are converted

The data migration `0267_backfill_authorized_users` translates RBAC tables into the legacy model with the following rules:

| RBAC row                             | Legacy effect                                      |
| ------------------------------------- | -------------------------------------------------- |
| `Product_Member` (any role, direct or via `Product_Group` \+ `Dojo_Group_Member`) | Adds the user to `Product.authorized_users`       |
| `Product_Type_Member` (any role, direct or via `Product_Type_Group` \+ `Dojo_Group_Member`) | Adds the user to `Product_Type.authorized_users` |
| `Global_Role(Owner)` (direct or via group) | Sets `User.is_superuser = True`                    |
| \`Global\_Role(Writer` | Maintainer |                                            |
| `Global_Role(Reader)`                | No global elevation — relies on per-product membership |

Per-product role granularity (Reader vs Writer vs Maintainer vs Owner) collapses to membership-only because the legacy model has no per-product role concept. `Dojo_Group` structure as a permission-bearing entity is also lost; only the flattened individual user memberships remain.

### Required actions

- **Database migrations run automatically on upgrade.** Existing access is carried forward into the legacy `authorized_users` model. Existing data is preserved.
- **Audit the upgrade in staging first.** A new `python manage.py preview_legacy_authorization_migration` management command is shipped in 2.59 to summarize what an upgrade would change against a given database. It is read-only. Recommended workflow: install 2.59 in a staging environment with a snapshot of your production database, run the command, review the summary, then upgrade production.
- **Migrating from OS to Pro?** A new `python manage.py reconcile_authorized_users_to_rbac` management command is available on Pro to bring any access changes you made under OS forward into Pro RBAC. It supports `--dry-run` and is idempotent.

### Pro customers are not impacted

DefectDojo Pro deployments retain full RBAC. The Pro UX is unchanged — same Members/Groups management surface as before.

## SSO providers are available in DefectDojo Pro only

Single sign-on (SAML, OIDC, Google, Okta, Azure AD, GitLab, Auth0, Keycloak, GitHub Enterprise, and remote-user header authentication) has been consolidated into DefectDojo Pro. Open source DefectDojo now exposes only local username/password login and the password-reset flow.

### Required actions

- **No customizations or local-only login:** No action required.
- **Currently logging in via SSO on open source:** Existing user accounts and group memberships are preserved on upgrade, but SSO sign-in will no longer work after 2.59. To keep an SSO-driven login experience, switch to [DefectDojo Pro](/content/site-root.html), which carries forward and extends the SSO surface (provider configuration moves to a UI-managed tuner).

## Removal: Questionnaire API Endpoints

As announced in DefectDojo 2.56.0, the following Questionnaire API endpoints have been removed:

- `/api/v2/questionnaire_answered_questionnaires/`
- `/api/v2/questionnaire_answers/`
- `/api/v2/questionnaire_engagement_questionnaires/`
- `/api/v2/questionnaire_general_questionnaires/`
- `/api/v2/questionnaire_questions`

### Required Actions

Any requests to these endpoints will now return a 404 Not Found error.

## Removal: Credential Manager

As announced in DefectDojo 2.57.0, the Credential Manager feature has been removed. The following API endpoints are no longer available:

- `/api/v2/credentials/`
- `/api/v2/credential_mappings/`

### Required Actions

Any requests to these endpoints will now return a 404 Not Found error. The Credential Manager UI is no longer available.

## Removal: Stub Findings

As announced in DefectDojo 2.57.0, the Stub Findings feature has been removed. The following API endpoint is no longer available:

- `/api/v2/stub_findings/`

### Required Actions

Any requests to this endpoint will now return a 404 Not Found error. The Stub Findings UI is no longer available.

## Configuration change in Watson Search Indexing

In [PR 14881](https://github.com/DefectDojo/django-DefectDojo/pull/14881) We optimized the way the Django Watson search index is updated during imports and reimports. There is not a single configuration setting to manage the threshold: `DD_WATSON_ASYNC_INDEX_UPDATE_BATCH_SIZE`. The default value should work fine for most instances.

## Dependency Check parser: related dependencies folded into the main finding

The Dependency Check parser previously created one finding per `<relatedDependency>` in the report, in addition to the finding for the main vulnerable dependency. Because OWASP Dependency-Check attaches the vulnerability only to the main dependency in the XML and the related entries are metadata pointing to other files in the same logical component, this produced N findings sharing the same title, CVE, component name and component version — only the file path differed. For projects with Spring Boot, ActiveMQ, or other libraries whose CPE matches many sibling artifacts this produced significant noise.

Starting in 2.59.1, the parser emits exactly one finding per vulnerability per main dependency. The file paths of any related dependencies are surfaced in the finding description under a `**Related Filepaths:**` block.

### Background: what `<relatedDependencies>` actually contains

OWASP Dependency-Check’s `DependencyBundlingAnalyzer` merges co-grouped artifacts into a single main dependency and lists the others under `<relatedDependencies>`. It does this under five scenarios:

1. **Identical content (`hashesMatch`)** — the same jar (matching sha1) found at multiple paths, e.g. the same library packaged into multiple ear/war archives.
2. **Shaded jar (`isShadedJar`)** — a `.jar` and a `pom.xml` extracted from inside it share the same CPE; the pom.xml is recorded as related.
3. **WebJar (`isWebJar`)** — a `.js` file extracted from a WebJar matches the jar’s CPE (mapped via `pkg:maven/org.webjars/<name>@<version>`); the js file is recorded as related to the jar.
4. **Same CPE + base path + vulnerabilities + filename match** — sibling artifacts in the same project that share a CPE. Example: `spring-boot`, `spring-boot-actuator`, `spring-boot-starter-jdbc`, etc. all map to the `spring_boot` CPE and are grouped under the main `spring-boot` jar.
5. **NPM same name + version** — the same npm package discovered via different resolution paths (for example `package-lock.json` plus `node_modules`).

Only scenario 1 represents the same vulnerable artifact at multiple deploy locations. Scenarios 2-5 are different files representing one logical component. Both cases were previously inflated into separate findings; both now collapse to one finding with the related paths listed in the description.

### Required actions

- **Users filtering or grouping by the `related` tag**: that tag is no longer applied because related findings are no longer created. Update any saved filters, dashboards, or rules that depend on it. Equivalent information is now available in the finding description (look for `**Related Filepaths:**`).
- **Reimport behavior**: on the next reimport of an existing Dependency Check report, the previously-created `related` findings will be closed as no longer present in the report. This is expected and matches the new parsing behavior.

For more information, check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/3.0.0).
