Skip to content

Release: Merge back 3.1.100 into dev from: master-into-dev/3.1.100-3.2.0-dev#15232

Merged
rossops merged 49 commits into
devfrom
master-into-dev/3.1.100-3.2.0-dev
Jul 13, 2026
Merged

Release: Merge back 3.1.100 into dev from: master-into-dev/3.1.100-3.2.0-dev#15232
rossops merged 49 commits into
devfrom
master-into-dev/3.1.100-3.2.0-dev

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Release triggered by rossops

DefectDojo release bot and others added 30 commits July 6, 2026 22:09
…2.0-dev

Release: Merge back 3.1.0 into bugfix from: master-into-bugfix/3.1.0-3.2.0-dev
* docs: add SSO user local-login fallback for open source

After upgrading to open-source DefectDojo 3.x, SSO becomes a Pro-only
feature and previously SSO-provisioned users are locked out: they have no
usable password, and the UI/API block setting one because such accounts are
detected as SSO accounts. Deleting and recreating them loses history and
permissions.

Add an Open Source docs page describing the backend workaround: set a local
password via the Django shell and enable force_password_reset so the user is
made to choose their own password on next login. Includes single-user and
bulk snippets, a Kubernetes variant, and the forgot-password alternative.
Cross-link it from the existing "SSO Users" section of the creating-new-users
page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: update command for accessing Django shell in SSO user local-login fallback

* Revise user management documentation

Updated example for a single user and removed bulk password reset section.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Adds the Microsoft Defender (MDVM) section to the Connectors tool
reference: license prerequisites (incl. the Standalone-vs-Add-on SKU
trap), Entra app registration walkthrough (Application permission +
admin consent gotchas), connector field mappings, device-group Record
model, and expected data timing (6h snapshot cycle, ~24h for new
devices, ~20min license propagation).

Pairs with DefectDojo-Inc/connectors#652 and DefectDojo-Inc/dojo-pro#1753
(story sc-13448).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… reports (#15159)

Reports filtered to a subset of scanners (e.g. SAST-only) contain the
other sections as explicit nulls ("iacScanResults": null), so
dict.get(key, {}) returns None and the chained .get() raises
AttributeError: 'NoneType' object has no attribute 'get'. A null
vulnerabilityDetails section likewise crashed CWE lookups with
TypeError: 'NoneType' object is not iterable.

Fall back to empty containers with (data.get(key) or {}) for
scanResults, iacScanResults and scaScanResults, and or [] for
vulnerabilityDetails.

Adds two regression fixtures covering each crash path: a SAST-only
report with null scanner sections and a populated CWE store, and a
variant with vulnerabilityDetails also null.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Expose effective dedupe matching policy on the Test API

Adds two read-only fields to TestSerializer, backed by the existing
Test model properties that the importer and dedupe machinery already
use on every import:

- deduplication_algorithm: legacy, unique_id_from_tool, hash_code, or
  unique_id_from_tool_or_hash_code
- hash_code_fields: the finding fields hashed for this test's scan
  type (null when the scan type has no per-scanner configuration and
  legacy default fields apply)

"Which fields are compared exactly?" is a recurring support question:
matching behavior differs per scanner and the answer currently lives
in settings.dist.py where users cannot see it. No new logic - this
only surfaces what the system already computes, making the effective
policy visible via the API and available for UIs to render.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Use typed serializer fields so schema generation stays warning-free

ReadOnlyField cannot be introspected by drf-spectacular (the CI schema
check runs --fail-on-warn), so declare the matching-policy fields with
their real types: CharField for deduplication_algorithm and a nullable
ListField of strings for hash_code_fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* guard endpoints usage

* render jira templates locations instead of guarding

* tests

* render locations in reports when v3, tests

* render locations on report api when necessary

* cleanup

* test fixes

---------

Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
)

close_old_findings iterated findings.values() — every column of every
finding in the test, including description — just to collect
is_mitigated, hash_code and unique_id_from_tool for the exclusion
filter. Narrow the values() call to those three columns.
#15186)

The per-batch post-processing dispatch read the push_to_jira flag
computed for the last finding of the batch and applied it to the whole
batch. With finding groups enabled and push_to_jira on, a mixed batch
ending in a grouped finding suppressed the JIRA push for every
ungrouped finding in the batch, and a batch ending in an ungrouped
finding pushed grouped findings individually.

Track each finding's own flag and partition the batch by flag at
dispatch time. Uniform batches (grouping disabled, push off) still
dispatch once, so task counts are unchanged for the common case.
Applies to both import and reimport.
…ton (#15187)

The intermediate-flush hook patches SearchContextManager.add_to_context at
class level, so it also fires inside update_watson_search_index_for_model's
own ad-hoc context. A task processing a full
WATSON_ASYNC_INDEX_UPDATE_BATCH_SIZE batch re-dispatches a clone of itself,
discards those pks unindexed, and loops forever: queue length stays ~0 while
the worker is pegged republishing the same batches, and nothing gets indexed.

Guard the hook so only the global singleton (the request-path context managed
by AsyncSearchContextMiddleware) intermediate-flushes. Ad-hoc context managers
index their own batch on end(), as stock watson does.

Extracted from the hardening half of #15165 for the bugfix branch.

Co-authored-by: dogboat <dogboat@users.noreply.github.com>
…Type names (#15149)

* fix(importers): stop doubling the (scan_type) suffix in dynamic Test Type names

Generic Findings Import (and other dynamic-test-type parsers like SARIF)
built the Test Type name by unconditionally appending " Scan ({scan_type})"
to the report's `type` field. When `type` already carried the
" ({scan_type})" suffix, the suffix was doubled, e.g.
"Prisma Cloud (Generic Findings Import) Scan (Generic Findings Import)".

Extract the name resolution into resolve_dynamic_test_type_name(), which is
now idempotent: a `type` already ending in " ({scan_type})" is used verbatim.
The intentional "{type} Scan ({scan_type})" format is unchanged for all other
cases (Tool1 -> "Tool1 Scan (Generic Findings Import)"), preserving SARIF and
existing behavior.

To avoid breaking existing data, the reimport validation accepts either the
new idempotent name or the legacy (pre-patch) name via
legacy_dynamic_test_type_name(), so reimports into tests whose test_type was
created with the old doubled name keep working without a mismatch error.

Also corrects the Generic Findings Import docs, which described a
"{Test Name} (Generic Findings Import)" format the code never produced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(importers): restore ' Scan'-suffix guard to stop re-doubling dynamic Test Type names

The idempotency rewrite dropped the legacy guard that returned the scan type
as-is when '{type} Scan' already equals the scan_type. That re-introduced the
exact doubling the PR removes for dynamic parsers whose scan_type ends in
' Scan' (Horusec, AWS Security Hub, Rusty Hog variants), e.g. 'Horusec Scan'
became 'Horusec Scan (Horusec Scan)' on fresh import. Restore the guard and add
a regression test importing a Horusec scan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Updated CODEOWNERS to change reviewers for all other code changes.
The location reference permission classes (LocationProductReferencePermission
and LocationFindingReferencePermission) now authorize the location foreign key
on create and update, alongside the existing product/finding authorization,
using the shared destination-check helpers. This keeps foreign-key
authorization consistent across the writable fields on these endpoints.

Adds API tests for the location reference write paths.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
)

The questionnaire relink routes (engagement_empty_survey and
existing_engagement_empty_survey) now use the same permission mapping as the
other questionnaire management routes, and engagement_empty_survey reuses the
source-engagement edit check already used by the existing-engagement view.
This keeps questionnaire handling consistent across the survey routes.

Adds unit coverage for the relink routes.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
)

* refactor(locations): use a shared helper for endpoint view object lookups

The endpoint (Location) views each resolved their object with an ad-hoc
get_object_or_404 (and one Location.objects.get). Route them all through a
single helper that fetches the Location from the standard location queryset,
consistent with the list and host views. Adds regression coverage for the
endpoint view lookups.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(locations): assert real cross-product denial status (400) for endpoint views

The cross-product tests asserted 404, but these views are guarded by the
AuthorizationMiddleware object check (URL_PERMISSIONS -> (object, Location, ...)),
and DefectDojo renders PermissionDenied via custom_unauthorized_view as HTTP 400
app-wide. Assert the actual denial status so the suite passes under
V3_FEATURE_LOCATIONS; the view-level get_authorized_locations lookup remains as
defense-in-depth. Security property (deny + object unchanged) is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
… via API (#15147)

* fix(risk_acceptance): reinstate findings when expiration date updated via API

RiskAcceptanceSerializer.update() never called ra_helper.reinstate() when
expiration_date changed, unlike the legacy Django view which does so at
engagement/views.py. This caused two bugs reported together:

1. Findings stayed Active after a user updated the expiration date from a
   past date to a future date via the Edit Risk Acceptance form (Vue UI).
   reinstate() sets them back to inactive/risk_accepted.

2. Findings stayed Inactive on subsequent expiry cycles. Because reinstate()
   was never called, expiration_date_handled was never cleared. The Celery
   expiration task filters on expiration_date_handled__isnull=True, so the
   RA was permanently excluded from every future expiry run.

Fix: capture old_expiration_date before super().update(), then call
ra_helper.reinstate() when the date changes — matching the logic that
already existed in the legacy view.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(risk_acceptance): regression coverage for reinstate on API expiration update

Adds two API tests exercising the serializer update() reinstate path:

- Extending an expired RA's expiration_date reinstates its findings
  (active=False / risk_accepted=True) and clears expiration_date_handled
  so the Celery expiry task re-processes it.
- Editing a never-expired RA's date leaves findings untouched and keeps
  expiration_date_handled None.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
#15204)

get_serializable_pghistory_context returned ctx.metadata.copy() verbatim, so a
non-JSON-serializable value in the active context (e.g. a user set to a User
object instead of its pk) made kombu raise EncodeError and abort task dispatch.
Coerce metadata to JSON-safe values (model instances -> pk, recursing into
dict/list/tuple) so a stray value can never crash dispatch.

Fixes DJANGO-42W8

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rnames (#15196)

* fix(notifications): deliver @mention notifications and match full usernames

* add regression tests for @mention delivery and username matching

* ruff lint and format
Document the Similar Findings feature on the View Finding page, with
separate Open Source and Pro pages (audience-scoped) reflecting the
distinct UIs: the collapsible filter panel in OS and the Duplicate &
Similar Findings card with tabs in Pro. Cover the matching fields, how
it differs from automatic deduplication, the manual mark-as-duplicate /
set-as-original actions, and the enable/disable system setting. Adds
screenshots and a cross-link from the deduplication overview.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ase-URL blocks (#15216)

The Doks docs theme (clipboard.js) only adds a copy button to fenced code
blocks that Hugo wraps in <div class="highlight">, which requires the fence
to declare a language. Two Report Builder blocks used a bare ``` fence and
therefore rendered as plain <pre> with no copy button:

- PRO__report_builder_llm.md: the self-contained LLM prompt users are meant
  to copy wholesale into Claude/ChatGPT
- PRO__report_builder_api.md: the API base-URL example

Tagging both fences as ```text matches the working Dashboards LLM guide and
gives every command/prompt in the Report Builder docs a copy button.

Authored by T. Walker - DefectDojo
Some Jira workflows reject a transition unless specific fields (e.g. a
Resolution and a justification custom field) are provided on the
transition screen. DefectDojo previously fired close/reopen transitions
with only a transition ID, making such workflows impossible to satisfy.

Adds JIRA_Project.close_transition_fields / reopen_transition_fields
(JSON, same pattern as custom_fields) which are sent as the `fields`
payload of jira.transition_issue() at every transition call site:
status pushes (close/reopen), deleted-finding close, and epic close.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Jira: support fields on close/reopen transitions
docs: Microsoft Defender connector setup guide
Document the HIBP findings connector: needs a Core-tier (or higher) API key
with domain search, and at least one verified domain on the HIBP account
before any breach data appears. Covers the Location/Secret mappings and that
DefectDojo creates a Record per verified domain with a finding per breach.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
Adds the CrowdStrike Falcon entry to the connectors tool reference: data types
(Spotlight vulnerabilities + EDR detections), required Falcon API client scopes,
region-specific base URLs, and connector mappings.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the Censys findings connector in the Pro connectors tool reference:
the Censys Platform tier and credentials required (Personal Access Token +
organization ID), the Location, the search query that scopes the import to
your own assets, that DefectDojo creates a Record per host and imports its
exposed services as findings, and the minimum-severity option.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
Document the Wazuh findings connector in the Pro connectors tool reference:
where to get the Wazuh Indexer endpoint and credentials, that the Location is
the Indexer URL (port 9200), that DefectDojo creates a Record per agent and
imports its detected CVEs as findings, and the minimum-severity option.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
Maffooch and others added 11 commits July 13, 2026 09:34
Document the Group-IB Attack Surface Management connector in the
Pro connectors tool reference and add it to the supported-tools list.

Covers Basic Auth (username = ASM login, password = API key), the fixed
https://asm.group-ib.com location, per-company Record discovery, assets
mapped as endpoints, incremental sync, and the optional company_id
scoping fallback.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the Docker Scout findings connector: needs a Docker PAT created by an
owner of a Docker organization enrolled in Docker Scout. Covers the Location
(https://api.scout.docker.com), Secret (PAT), and Organization mappings, and
that DefectDojo creates a Record per Docker Scout stream with summary findings
(the metrics exporter reports aggregate counts, not per-CVE).

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
…, HackerOne, Shodan setup (#15199)

* docs(connectors): Contrast, GitGuardian, Google Cloud SCC, HackerOne, Shodan setup

Add tool-specific setup sections to the connector reference for five
findings connectors, following the existing per-tool format
(description, prerequisites, connector mappings).

- Contrast: username + API key + service key + organization id.
- GitGuardian: single API key; documents the leak-proof behavior
  (only incident metadata is imported, never the secret value) and the
  open-incident / auto-mitigation semantics.
- Google Cloud Security Command Center: service-account JSON key +
  parent resource; notes SCC activation and the findingsViewer role.
- HackerOne: organization API token (identifier + token), with the
  personal-vs-organization token caveat.
- Shodan: API key + search query scoping to the org's own assets;
  notes the membership requirement and query-credit usage.

Veracode and Qualys are covered separately in the connector-docs
backfill PR (#15198).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(connectors): add Cloudflare setup section

Cloudflare WAF/edge-security connector: Security Center insights per
zone, API token auth, auto-discovered accounts/zones. Added alongside
the other findings-connector sections in this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
…tVM, Veracode (#15198)

Backfills the connector reference for four connectors that had no
customer-facing docs. Each section covers credential/token setup, the
connector field mappings, and what a Record maps to:

- GitHub Advanced Security — PAT scopes (code scanning / Dependabot /
  secret scanning), org, api.github.com vs GHES.
- Qualys — VMDR API user + per-subscription platform (pod) URL.
- Rapid7 InsightVM — Security Console URL (:3780) + console credentials.
- Veracode — API ID + secret (HMAC) + regional API base URL.

Stories: sc-13490, sc-12691, sc-13485, sc-13464

Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
#15197)

Setup and usage for the Defender for Cloud connector: required Defender
plans (Servers Plan 2, Containers), Entra app registration + the three
credential values, the Security Reader RBAC assignment on the service
principal (per subscription), connector field mappings, and scan-timing
expectations. Distinguishes it from the device-based Microsoft Defender
connector.

Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
…test render (#15226)

* docs(jira): Pro Jira integrator guide - auth methods, minimum scopes, OAuth setup

- Document the Basic, PAT, OAuth 2.0 (3LO), and service-account token auth methods.
- Absolute-minimum classic and granular scopes.
- OAuth app setup: Resource-level access type and 3LO callback registration.
- Behavioral notes: internal gateway API base vs public browse URL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(jira): document custom fields, ticket templates, and test render

Extend the Jira integrator guide with the mapping features shipped in the
Jira work:

- Custom Fields: source / value / vendor-field / application-point model,
  including the Vendor Field display-name -> internal-id picker
  (e.g. "DD Close Justification" -> customfield_10255) and transition-scoped
  fields (e.g. a resolution required on close).
- Ticket Templates: customer-authored Finding & Finding Group summary and
  description with built-in-default fallback, plus Test render to preview
  output against sample data before saving.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Paul Osinski <42211303+paulOsinski@users.noreply.github.com>
…/ JSM Assets setup (#15153)

* docs: Asset Connectors concept + Azure DevOps, Bitbucket, GitLab, JSM Assets setup

Documents the new Asset Connector type (inventory reconciliation
instead of findings import, NEW/MISSING lifecycle, auto-created
Products and Product Types) and adds tool-specific setup sections for
the four new asset connectors, including the auth requirements
verified against the live vendor APIs: GitLab read_api PAT and
pending-deletion handling; JSM Premium plan + agent-seat requirement;
Bitbucket scoped-token requirement and mandatory workspace slugs;
Azure DevOps PAT read scopes and org URL normalization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: fix AWS Security Hub section split by Asset Connector inserts

The Azure DevOps and Bitbucket sections were inserted between AWS Security Hub's
Prerequisites and its own Connector Mappings, orphaning the AWS 'us-east-1'
mapping instructions after Bitbucket. Move AWS's Connector Mappings back under
its Prerequisites so the alphabetical order is AWS Security Hub -> Azure DevOps
-> Bitbucket -> BurpSuite with each section intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
Release: Merge release into master from: release/3.1.100
@github-actions

Copy link
Copy Markdown
Contributor Author

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions

Copy link
Copy Markdown
Contributor Author

Conflicts have been resolved. A maintainer will review the pull request shortly.

@github-actions github-actions Bot added New Migration Adding a new migration file. Take care when merging. settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR apiv2 docs unittests ui parser helm labels Jul 13, 2026
The merge back from master reintroduced master's class-based wrapper
signature `(self, engine, obj)` on top of dev's instance-based patch of
`search_context_manager.add_to_context`. Assigning to the instance means
Python never binds `self`, so watson's post_save calls the wrapper with
`(engine, obj)` and it blows up with "missing required positional
argument: 'obj'".

That killed the calculate_grade and post_process_findings_batch celery
tasks whenever product grading was on, which cascaded into the perf test
UnboundLocalErrors and zeroed-out query counts.

Restore dev's `(engine, obj)` signature and drop the now-moot
singleton guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rossops rossops merged commit ad76b1b into dev Jul 13, 2026
150 checks passed
@rossops rossops deleted the master-into-dev/3.1.100-3.2.0-dev branch July 13, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apiv2 docs helm New Migration Adding a new migration file. Take care when merging. parser release-management Automated release-train PR settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR ui unittests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants