Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c58f90e
Update versions in application files
Nov 10, 2025
1622df3
Merge pull request #13669 from DefectDojo/master-into-bugfix/2.52.1-2…
rossops Nov 10, 2025
cf2a8b1
:bug: harden jfrog xray unified file parsing #13628 (#13632)
manuel-sommer Nov 10, 2025
c484229
feat(renovate): track oldest maintained k8s (#13670)
kiblik Nov 12, 2025
517c14c
:lipstick: beautify drheader jsonfiles (#13672)
manuel-sommer Nov 12, 2025
c7432c1
:tada: Advance ibm app parser with fix_available (#13663)
manuel-sommer Nov 12, 2025
3396e7b
:tada: add Dawnscanner fix_available field. (#13660)
manuel-sommer Nov 12, 2025
186befb
:bug: fix nancy severity calculation #13656 (#13657)
manuel-sommer Nov 12, 2025
99a1d7e
:bug: fix debug mode in logging #13659 (#13662)
manuel-sommer Nov 12, 2025
0ff017f
:tada: implement new threatmapper file format #13639 (#13655)
manuel-sommer Nov 13, 2025
573e263
:tada: Add VA vulnid (#13675)
manuel-sommer Nov 13, 2025
038cf16
:tada: Add Kubeaudit fix_available field (#13684)
manuel-sommer Nov 13, 2025
b097ced
feat(helm): Relocate docs/schema hints
kiblik Nov 13, 2025
856aa7a
feat(renovate): Wait 2 days to use latest k8s (#13694)
kiblik Nov 13, 2025
2171863
fix(helm/renovate/dependabot): Commit changes & fix condition format …
kiblik Nov 13, 2025
ed83097
reimport: support pro hash method (#13680)
valentijnscholten Nov 13, 2025
3ce29cb
:bug: fix DD_EDITABLE_MITIGATED_DATA close finding internal server er…
manuel-sommer Nov 14, 2025
769231d
:bug: add user mention notifications in note creation for Engagement,…
Maffooch Nov 14, 2025
44ebefb
:tada: Add pwn sast fix_available field (#13702)
manuel-sommer Nov 14, 2025
3fb802b
Qualys parser add CVEs to vulnerability ids for xml files
Jino-T Nov 14, 2025
c8b521a
Add CVE assertions to Qualys parser tests for vulnerability IDs
Maffooch Nov 14, 2025
2593926
:bug: fix finding closed with a provided mitigated date #13699 (#13700)
manuel-sommer Nov 17, 2025
3d3427b
[docs] typo fixes (#13709)
paulOsinski Nov 17, 2025
b5a7f9e
Refactor CVE extraction in parse_finding to use list comprehensions f…
Maffooch Nov 17, 2025
9d83ea6
Merge pull request #13698 from kiblik/helm_hit_help
rossops Nov 17, 2025
3096b0a
Merge pull request #13710 from Jino-T/qualys-fix
rossops Nov 17, 2025
c1387b7
Update versions in application files
Nov 17, 2025
69536d9
Merge pull request #13718 from DefectDojo/release/2.52.2
rossops Nov 17, 2025
ed37199
Update versions in application files
Nov 17, 2025
6f0897a
Merge branch 'dev' into master-into-dev/2.52.2-2.53.0-dev
Maffooch Nov 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@
"matchDatasources": "github-releases",
"matchPackageNames": "renovatebot/renovate",
"schedule": ["* * * * 0"]
},{
"description": "Minikube does not like freshly released k8s. We need to wait some time so it will be adopted",
"matchDatasources": [
"custom.endoflife-oldest-maintained",
"github-releases"
],
"matchPackageNames": [
"kubernetes",
"kubernetes/kubernetes"
],
"minimumReleaseAge": "2 days"
}],
"customDatasources": {
"endoflife-oldest-maintained": {
Expand Down
21 changes: 13 additions & 8 deletions .github/workflows/test-helm-chart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ jobs:
if: startsWith(github.head_ref, 'renovate/') || startsWith(github.head_ref, 'dependabot/')
run: |
yq -i '.annotations."artifacthub.io/changes" += "- kind: changed\n description: ${{ github.event.pull_request.title }}\n"' helm/defectdojo/Chart.yaml
git add helm/defectdojo/Chart.yaml
git commit -m "ci: update Chart annotations from PR #${{ github.event.pull_request.number }}" || echo "No changes to commit"

- name: Run helm-docs (update)
uses: losisin/helm-docs-github-action@a57fae5676e4c55a228ea654a1bcaec8dd3cf5b5 # v1.6.2
Expand All @@ -123,27 +125,25 @@ jobs:
chart-search-root: "helm/defectdojo"
git-push: true

# Documentation provided in the README file needs to contain the latest information from `values.yaml` and all other related assets.
# If this step fails, install https://github.com/norwoodj/helm-docs and run locally `helm-docs --chart-search-root helm/defectdojo` before committing your changes.
# The helm-docs documentation will be generated for you.
- name: Run helm-docs (check)
uses: losisin/helm-docs-github-action@a57fae5676e4c55a228ea654a1bcaec8dd3cf5b5 # v1.6.2
if: ! startsWith(github.head_ref, 'renovate/') || startsWith(github.head_ref, 'dependabot/')
if: ${{ !(startsWith(github.head_ref, 'renovate/') || startsWith(github.head_ref, 'dependabot/')) }}
with:
fail-on-diff: true
chart-search-root: "helm/defectdojo"

- name: Failed Information
if: failure()
run: |-
echo "Your HELM chart changed but you haven't adjusted documentation. Check https://github.com/defectdojo/django-DefectDojo/tree/master/helm/defectdojo#helm-docs-update for more information."

generate_schema:
name: Update schema
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

# The HELM structure supports the existence of a `values.schema.json` file. This file is used to validate all values provided by the user before Helm starts rendering templates.
# The chart needs to have a `values.schema.json` file that is compatible with the default `values.yaml` file.
# If this step fails, install https://github.com/losisin/helm-values-schema-json and run locally `helm schema --use-helm-docs` in `helm/defectdojo` before committing your changes.
# The helm schema will be generated for you.
- name: Generate values schema json
uses: losisin/helm-values-schema-json-action@660c441a4a507436a294fc55227e1df54aca5407 # v2.3.1
with:
Expand All @@ -152,6 +152,11 @@ jobs:
useHelmDocs: true
values: values.yaml

- name: Failed Information
if: failure()
run: |-
echo "Your HELM chart changed but you haven't adjusted schema. Check https://github.com/defectdojo/django-DefectDojo/tree/master/helm/defectdojo#helm-schema-update for more information."

lint_format:
name: Lint chart (format)
runs-on: ubuntu-latest
Expand Down
12 changes: 5 additions & 7 deletions docs/content/en/connecting_your_tools/import_intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@ description: "Learn how to import data manually, through the API, or via a conne
weight: 1
---

One of the things we understand at DefectDojo is that every company’s security needs are completely different. There is no ‘one\-size\-fits\-all’ approach. As your organization changes, having a flexible approach is key.

DefectDojo allows you to connect your security tools in a flexible way to match those changes.
One of the things we understand at DefectDojo is that every company’s security needs are completely different. There is no one-size-fits-all approach. As your organization changes, having a flexible approach is key, and DefectDojo allows you to connect your security tools in a flexible way to match those changes.

## Scan Upload Methods

When DefectDojo receives a vulnerability report from a security tool, it will create Findings based on the vulnerabilities contained within that report. DefectDojo acts as the central repository for these Findings where they can be triaged, remediated or otherwise addressed by you and your team.
When DefectDojo receives a vulnerability report from a security tool, it will create Findings based on the vulnerabilities contained within that report. DefectDojo acts as the central repository for these Findings where they can be triaged, remediated, or otherwise addressed by you and your team.

There are two main ways that DefectDojo can upload Finding reports.

* Via direct **import** through the UI: [Import Scan Form](../import_scan_files/import_scan_ui)
* Via **API** endpoint (allowing for automated data ingest): See [API Docs](https://docs.defectdojo.com/en/api/api-v2-docs/)
* Via **API** endpoint (allowing for automated data ingestion): See [API Docs](https://docs.defectdojo.com/en/api/api-v2-docs/)

#### DefectDojo Pro Methods

Expand All @@ -29,8 +27,8 @@ There are two main ways that DefectDojo can upload Finding reports.

| | **UI Import** | **API** | **Connectors** <span style="background-color:rgba(242, 86, 29, 0.3)">(Pro)</span> | **Smart Upload** <span style="background-color:rgba(242, 86, 29, 0.3)">(Pro)</span>|
| --- | --- | --- | --- | --- |
| **Supported Scan Types** | All: see [Supported Tools](/supported_tools/) | All: see [Supported Tools](/supported_tools/) | Snyk, Semgrep, Burp Suite, AWS Security Hub, Probely, Checkmarx, Tenable | Nexpose, NMap, OpenVas, Qualys, Tenable |
| **Automation?** | Available via API: `/reimport` `/import` endpoints | Triggered from [CLI Importer](../external_tools) or external code | Connectors is inherently automated | Available via API: `/smart_upload_import` endpoint |
| **Supported Scan Types** | All: see [Supported Tools](/supported_tools/) | All: see [Supported Tools](/supported_tools/) | Anchore, AWS Security Hub, BurpSuite, Checkmarx ONE, Dependency-Track, Probely, Semgrep, SonarQube, Snyk, Tenable, Wiz | Nexpose, NMap, OpenVas, Qualys, Tenable |
| **Automation?** | Available via API: `/reimport` `/import` endpoints | Triggered from [CLI Importer](../external_tools) or external code | Connectors is an inherently automated feature | Available via API: `/smart_upload_import` endpoint |

### Product Hierarchy and organization

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,17 @@ Tests always have:
* an associated test **Environment**
* an associated **Engagement**

Tests can be created in different ways. Tests can be automatically created when scan data is imported directly into to an Engagement, resulting in a new Test containing the scan data. Tests can also be created in anticipation of planning future engagements, or for manually entered security findings requiring tracking and remediation.
Tests can be created in different ways. Tests can be automatically created when scan data is imported directly into an Engagement, resulting in a new Test containing the scan data. Tests can also be created in anticipation of planning future engagements, or for manually entered security findings requiring tracking and remediation.

### **Test Types**

DefectDojo supports two categories of Test Types:

1. **Parser-based Test Types**: These correspond to specific security scanners that produce output in formats like XML, JSON, or CSV. When importing scan results, DefectDojo uses specialized parsers to convert the scanner output into Findings.

2. **Non-parser Test Types**: These are used for manually created findings not imported from a scan files.
The following Test Types appear in the "Scan Type" dropdown when creating a new test, but will not appear when selecting "Import Scan":
2. **Non-parser Test Types**: These are used for manually created Findings not imported from scan files. These Test Types use the [Generic Findings Import](/supported_tools/parsers/generic_findings_import/) method to render Findings and metadata.

The following Test Types appear in the "Scan Type" dropdown when creating a new test.
* API Test
* Static Check
* Pen Test
Expand Down
2 changes: 1 addition & 1 deletion docs/content/supported_tools/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ DefectDojo can parse data from 200+ security reports and counting.

| [Connectors](/en/connecting_your_tools/connectors/about_connectors/): supported tools | [Smart Upload](/en/connecting_your_tools/import_scan_files/smart_upload/): supported tools |
| --- | --- |
| AWS Security Hub, BurpSuite, Checkmarx ONE, Dependency-Track, Probely, Semgrep, SonarQube, Snyk, Tenable | Nexpose, NMap, OpenVas, Qualys, Tenable, Wiz |
| Anchore, AWS Security Hub, BurpSuite, Checkmarx ONE, Dependency-Track, Probely, Semgrep, SonarQube, Snyk, Tenable | Nexpose, NMap, OpenVas, Qualys, Tenable, Wiz |

# All Supported Tools

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ Open-source and Pro users can use Generic Findings Import as a method to ingest

Using Generic Findings Import will create a new Test Type in your DefectDojo instance called "`{The Name Of Your Test}` (Generic Findings Import)". For example, this JSON content will result in a Test Type called "Example Report (Generic Findings Import)":

```
{
"name": "Example Report",
"findings": []
}
```

DefectDojo Pro users can also consider using the [Universal Parser](../universal_parser), a tool which allows for highly customizable JSON, XML and CSV imports.

For more information on supported parameters for Generic Findings Import, see the [Parser Guide](../file/generic)
For more information on supported parameters for Generic Findings Import, see the related [Parser Guide](../file/generic).
29 changes: 29 additions & 0 deletions dojo/api_v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from django.db.models.query import QuerySet as DjangoQuerySet
from django.http import FileResponse, HttpResponse
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils import timezone
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.renderers import OpenApiJsonRenderer2
Expand Down Expand Up @@ -176,6 +177,7 @@
generate_file_response,
get_setting,
get_system_setting,
process_tag_notifications,
)

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -528,6 +530,15 @@ def notes(self, request, pk=None):
)
note.save()
engagement.notes.add(note)
# Determine if we need to send any notifications for user mentioned
process_tag_notifications(
request=request,
note=note,
parent_url=request.build_absolute_uri(
reverse("view_engagement", args=(engagement.id,)),
),
parent_title=f"Engagement: {engagement.name}",
)

serialized_note = serializers.NoteSerializer(
{"author": author, "entry": entry, "private": private},
Expand Down Expand Up @@ -1086,6 +1097,15 @@ def notes(self, request, pk=None):
)
note.save()
finding.notes.add(note)
# Determine if we need to send any notifications for user mentioned
process_tag_notifications(
request=request,
note=note,
parent_url=request.build_absolute_uri(
reverse("view_finding", args=(finding.id,)),
),
parent_title=f"Finding: {finding.title}",
)

if finding.has_jira_issue:
jira_helper.add_comment(finding, note)
Expand Down Expand Up @@ -2135,6 +2155,15 @@ def notes(self, request, pk=None):
)
note.save()
test.notes.add(note)
# Determine if we need to send any notifications for user mentioned
process_tag_notifications(
request=request,
note=note,
parent_url=request.build_absolute_uri(
reverse("view_test", args=(test.id,)),
),
parent_title=f"Test: {test.title}",
)

serialized_note = serializers.NoteSerializer(
{"author": author, "entry": entry, "private": private},
Expand Down
26 changes: 20 additions & 6 deletions dojo/finding/helper.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
from contextlib import suppress
from datetime import datetime
from time import strftime

from django.conf import settings
Expand All @@ -9,6 +10,7 @@
from django.dispatch.dispatcher import receiver
from django.urls import reverse
from django.utils import timezone
from django.utils.timezone import is_naive, make_aware, now
from fieldsignals import pre_save_changed

import dojo.jira_link.helper as jira_helper
Expand Down Expand Up @@ -797,6 +799,17 @@ def save_vulnerability_ids_template(finding_template, vulnerability_ids):
finding_template.cve = None


def normalize_datetime(value):
"""Ensure value is timezone-aware datetime."""
if value:
if not isinstance(value, datetime):
value = datetime.combine(value, datetime.min.time())
# Make timezone-aware if naive
if is_naive(value):
value = make_aware(value)
return value


def close_finding(
*,
finding,
Expand All @@ -818,15 +831,16 @@ def close_finding(
"""
# Core status updates
finding.is_mitigated = is_mitigated
now = timezone.now()
finding.mitigated = mitigated or now
current_time = now()
mitigated_date = normalize_datetime(mitigated) or current_time
finding.mitigated = mitigated_date
finding.mitigated_by = mitigated_by or user
finding.active = False
finding.false_p = bool(false_p)
finding.out_of_scope = bool(out_of_scope)
finding.duplicate = bool(duplicate)
finding.under_review = False
finding.last_reviewed = finding.mitigated
finding.last_reviewed = mitigated_date
finding.last_reviewed_by = user

# Create note if provided
Expand All @@ -836,16 +850,16 @@ def close_finding(
entry=note_entry,
author=user,
note_type=note_type,
date=finding.mitigated,
date=mitigated_date,
)
finding.notes.add(new_note)

# Endpoint statuses
for status in finding.status_finding.all():
status.mitigated_by = finding.mitigated_by
status.mitigated_time = finding.mitigated
status.mitigated_time = mitigated_date
status.mitigated = True
status.last_modified = timezone.now()
status.last_modified = current_time
status.save()

# Risk acceptance
Expand Down
2 changes: 2 additions & 0 deletions dojo/finding/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1145,12 +1145,14 @@ def close_finding(request, fid):
note_type_activation = Note_Type.objects.filter(is_active=True)
missing_note_types = get_missing_mandatory_notetypes(finding) if len(note_type_activation) else note_type_activation
form = CloseFindingForm(
instance=finding,
missing_note_types=missing_note_types,
can_edit_mitigated_data=finding_helper.can_edit_mitigated_data(request.user),
)
if request.method == "POST":
form = CloseFindingForm(
request.POST,
instance=finding,
missing_note_types=missing_note_types,
can_edit_mitigated_data=finding_helper.can_edit_mitigated_data(request.user),
)
Expand Down
1 change: 1 addition & 0 deletions dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -1949,6 +1949,7 @@ def saml2_attrib_map_format(din):
"TS-": """https://tailscale.com/security-bulletins#""", # e.g. https://tailscale.com/security-bulletins or https://tailscale.com/security-bulletins#ts-2022-001-1243
"TYPO3-": "https://typo3.org/security/advisory/", # e.g. https://typo3.org/security/advisory/typo3-core-sa-2025-010
"USN-": "https://ubuntu.com/security/notices/", # e.g. https://ubuntu.com/security/notices/USN-6642-1
"VA-": "https://cvepremium.circl.lu/vuln/", # e.g. https://cvepremium.circl.lu/vuln/va-25-282-01
"VAR-": "https://cvepremium.circl.lu/vuln/", # e.g. https://cvepremium.circl.lu/vuln/var-201801-0152
"VNS": "https://vulners.com/",
"WID-SEC-W-": "https://cvepremium.circl.lu/vuln/", # e.g. https://cvepremium.circl.lu/vuln/wid-sec-w-2025-1468
Expand Down
5 changes: 4 additions & 1 deletion dojo/tools/dawnscanner/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ def get_findings(self, filename, test):
if item["message"][0:2] != "b,"
else item["message"][0:-1]
)

finding = Finding(
title=item["name"],
test=test,
Expand All @@ -42,6 +41,10 @@ def get_findings(self, filename, test):
static_finding=True,
dynamic_finding=False,
)
if item.get("remediation"):
finding.fix_available = True
else:
finding.fix_available = False

if self.CVE_REGEX.match(item["name"]):
finding.unsaved_vulnerability_ids = [
Expand Down
Loading
Loading