Skip to content

Commit 11749c1

Browse files
authored
Merge pull request #13992 from DefectDojo/release/2.53.5
Release: Merge release into master from: release/2.53.5
2 parents 5378d38 + 6811144 commit 11749c1

File tree

22 files changed

+413
-53
lines changed

22 files changed

+413
-53
lines changed

.github/dependabot.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,3 @@ updates:
6464
versions:
6565
- ">= 4.a"
6666
- "< 5"
67-
- package-ecosystem: docker
68-
directory: "/"
69-
schedule:
70-
interval: weekly
71-
open-pull-requests-limit: 10
72-
target-branch: dev
73-

.github/renovate.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
"components/package.json",
1414
"components/package-lock.json",
1515
"dojo/components/yarn.lock",
16-
"dojo/components/package.json",
17-
"Dockerfile**"
16+
"dojo/components/package.json"
1817
],
1918
"ignoreDeps": [],
2019
"packageRules": [{

.github/workflows/rest-framework-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858

5959
# no celery or initializer needed for unit tests
6060
- name: Unit tests
61-
timeout-minutes: 15
61+
timeout-minutes: 20
6262
run: docker compose up --no-deps --exit-code-from uwsgi uwsgi
6363
env:
6464
DJANGO_VERSION: ${{ matrix.os }}

components/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "defectdojo",
3-
"version": "2.53.4",
3+
"version": "2.53.5",
44
"license" : "BSD-3-Clause",
55
"private": true,
66
"dependencies": {

docs/content/en/working_with_findings/organizing_engagements_tests/product_hierarchy.md

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ Product Types can have Role\-Based Access Control rules applied, which limit tea
2525

2626
#### What can a Product Type represent?
2727

28-
* If a particular software project has many distinct deployments or versions, it may be worth creating a single Product Type which covers the scope of the entire project, and having each version exist as individual Products.
28+
* If a particular software project has many distinct deployments or versions, it may be worth creating a single Product Type which covers the scope of the entire project, and having each version exist as individual Products.
2929
30-
* You also might consider using Product Types to represent stages in your software development process: one Product Type for 'In Development', one Product Type for 'In Production', etc.
30+
* You also might consider using Product Types to represent stages in your software development process: one Product Type for 'In Development', one Product Type for 'In Production', etc.
3131
3232
* Ultimately, it's your decision how you wish to organize your Products, and what you Product Type to represent. Your DefectDojo hierarchy may need to change to fit your security teams' needs.
3333

@@ -58,11 +58,11 @@ The following scenarios are good reasons to consider creating a separate DefectD
5858
* "**ExampleProduct 1\.0**" uses completely different software components from "**ExampleProduct 2\.0**", and both versions are actively supported by your company.
5959
* The team assigned to work on "**ExampleProduct version A**" is different than the product team assigned to work on "**ExampleProduct version B**", and needs to have different security permissions assigned as a result.
6060

61-
These variations within a single Product can also be handled at the Engagement level. Note that Engagements don't have access control in the way Products and Product Types do.
61+
These variations within a single Product can also be handled at the Engagement level. Note that Engagements don't have access control in the way Products and Product Types do.
6262

6363
## **Engagements**
6464

65-
Once a Product is set up, you can begin creating and scheduling Engagements. Engagements are meant to represent moments in time when testing is taking place, and contain one or more **Tests**.
65+
Once a Product is set up, you can begin creating and scheduling Engagements. Engagements are meant to represent moments in time when testing is taking place, and contain one or more **Tests**.
6666

6767
Engagements always have:
6868

@@ -72,12 +72,12 @@ Engagements always have:
7272
* an assigned **Testing Lead**
7373
* an associated **Product**
7474

75-
There are two types of Engagement: **Interactive** and **CI/CD**.
75+
There are two types of Engagement: **Interactive** and **CI/CD**.
7676

7777
* An **Interactive Engagement** is typically run by an engineer. Interactive Engagements are focused on testing the application while the app is running, using an automated test, human tester, or any activity “interacting” with the application functionality. See [OWASP's definition of IAST](https://owasp.org/www-project-devsecops-guideline/latest/02c-Interactive-Application-Security-Testing#:~:text=Interactive%20Application%20Security%20Testing,interacting%E2%80%9D%20with%20the%20application%20functionality.).
7878
* A **CI/CD Engagement** is for automated integration with a CI/CD pipeline. CI/CD Engagements are meant to import data as an automated action, triggered by a step in the release process.
7979

80-
Engagements can be tracked using DefectDojo's **Calendar** view.
80+
Engagements can be tracked using DefectDojo's **Calendar** view.
8181

8282
#### What can an Engagement represent?
8383

@@ -91,7 +91,7 @@ If you have a planned testing effort scheduled, an Engagement offers you a place
9191

9292
* **Test:** Nessus Scan Results (March 12\)
9393
* **Test:** NPM Scan Audit Results (March 12\)
94-
* **Test:** Snyk Scan Results (March 12\)
94+
* **Test:** Snyk Scan Results (March 12\)
9595
9696
You can also organize CI/CD Test results within an Engagement. These kinds of Engagements are 'Open\-Ended' meaning that they don't have a date, and will instead add additional data each time the associated CI/CD actions are run.
9797

@@ -137,6 +137,29 @@ The following Test Types appear in the "Scan Type" dropdown when creating a new
137137

138138
Non-parser Test Types should be used when you need to manually create findings that require remediation but don't originate from automated scanner output.
139139

140+
#### **Parser-based Test Types**
141+
142+
Parser-based test types can be categorized by how their test type name is determined:
143+
144+
- **Fixed Test Type Names**: The test type name is predefined and known before import (e.g., "ZAP Scan", "Nessus Scan").
145+
146+
- **Report-Defined Test Type Names**: The test type name is extracted from the scan report content at import time.
147+
148+
Examples include:
149+
- **Generic Findings Import**: Creates test types based on the `type` field in JSON reports
150+
- **SARIF**: Creates test types based on tool names in the SARIF report (e.g., "Dockle Scan (SARIF)")
151+
- **OpenReports**: Creates separate test types per source found in the report
152+
153+
**Report-Defined Test Type Naming Rules:**
154+
- If the report's `type` field equals the scan type → uses scan type directly (e.g., "Generic Findings Import")
155+
- If the report's `type` field differs → creates "{type} Scan ({scan_type})" format (e.g., "Tool1 Scan (Generic Findings Import)")
156+
- If no `type` field is provided → uses scan type directly
157+
158+
**Important Considerations:**
159+
- Report-defined test types are automatically created when a new type is detected during import or reimport.
160+
- For reimports, the test type name must match exactly - mismatches will raise a validation error
161+
- Deduplication settings (`HASHCODE_FIELDS_PER_SCANNER`) use test type names as keys, so report-defined names must be configured accordingly if you want custom deduplication behavior
162+
140163
#### **How do Tests interact with each other?**
141164

142165
Tests take your testing data and group it into Findings. Generally, security teams will be running the same testing effort repeatedly, and Tests in DefectDojo allow you to handle this process in an elegant way.

dojo/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
# Django starts so that shared_task will use this app.
55
from .celery import app as celery_app # noqa: F401
66

7-
__version__ = "2.53.4"
7+
__version__ = "2.53.5"
88
__url__ = "https://github.com/DefectDojo/django-DefectDojo"
99
__docs__ = "https://documentation.defectdojo.com"

dojo/finding/deduplication.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,18 @@ def is_deduplication_on_engagement_mismatch(new_finding, to_duplicate_finding):
196196

197197

198198
def get_endpoints_as_url(finding):
199-
return [hyperlink.parse(str(e)) for e in finding.endpoints.all()]
199+
# Fix for https://github.com/DefectDojo/django-DefectDojo/issues/10215
200+
# When endpoints lack a protocol (scheme), str(e) returns a string like "10.20.197.218:6379"
201+
# without the "//" prefix. hyperlink.parse() then misinterprets the hostname as the scheme.
202+
# We replicate the behavior from dojo/endpoint/utils.py line 265: prepend "//" if "://" is missing
203+
# to ensure hyperlink.parse() correctly identifies host, port, and path components.
204+
urls = []
205+
for e in finding.endpoints.all():
206+
endpoint_str = str(e)
207+
if "://" not in endpoint_str:
208+
endpoint_str = "//" + endpoint_str
209+
urls.append(hyperlink.parse(endpoint_str))
210+
return urls
200211

201212

202213
def are_urls_equal(url1, url2, fields):

dojo/finding/views.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -968,8 +968,9 @@ def process_jira_form(self, request: HttpRequest, finding: Finding, context: dic
968968
logger.debug("jform.jira_issue: %s", context["jform"].cleaned_data.get("jira_issue"))
969969
logger.debug(JFORM_PUSH_TO_JIRA_MESSAGE, context["jform"].cleaned_data.get("push_to_jira"))
970970
# can't use helper as when push_all_jira_issues is True, the checkbox gets disabled and is always false
971+
push_to_jira_checkbox = context["jform"].cleaned_data.get("push_to_jira")
971972
push_all_jira_issues = jira_helper.is_push_all_issues(finding)
972-
push_to_jira = push_all_jira_issues or context["jform"].cleaned_data.get("push_to_jira")
973+
push_to_jira = push_all_jira_issues or push_to_jira_checkbox or jira_helper.is_keep_in_sync_with_jira(finding)
973974
logger.debug("push_to_jira: %s", push_to_jira)
974975
logger.debug("push_all_jira_issues: %s", push_all_jira_issues)
975976
logger.debug("has_jira_group_issue: %s", finding.has_jira_group_issue)
@@ -996,12 +997,6 @@ def process_jira_form(self, request: HttpRequest, finding: Finding, context: dic
996997
jira_helper.finding_link_jira(request, finding, new_jira_issue_key)
997998
jira_message = "Linked a JIRA issue successfully."
998999
# any existing finding should be updated
999-
jira_instance = jira_helper.get_jira_instance(finding)
1000-
push_to_jira = (
1001-
push_to_jira
1002-
and not (push_to_jira and finding.finding_group)
1003-
and (finding.has_jira_issue or (jira_instance and jira_instance.finding_jira_sync))
1004-
)
10051000
# Determine if a message should be added
10061001
if jira_message:
10071002
messages.add_message(

dojo/importers/base_importer.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,34 @@ def consolidate_dynamic_tests(self, tests: list[Test]) -> list[Finding]:
205205
if not self.test:
206206
# Determine if we should use a custom test type name
207207
if test_raw.type:
208-
test_type_name = f"{tests[0].type} Scan"
209-
if test_type_name != self.scan_type:
210-
test_type_name = f"{test_type_name} ({self.scan_type})"
208+
# If test_raw.type equals scan_type, use scan_type directly
209+
if test_raw.type == self.scan_type:
210+
test_type_name = self.scan_type
211+
else:
212+
test_type_name = f"{tests[0].type} Scan"
213+
if test_type_name != self.scan_type:
214+
test_type_name = f"{test_type_name} ({self.scan_type})"
211215
self.test = self.create_test(test_type_name)
216+
else:
217+
# During reimport, validate that the test_type matches
218+
# Calculate the expected test_type_name from the incoming report
219+
expected_test_type_name = self.scan_type
220+
if test_raw.type:
221+
# If test_raw.type equals scan_type, use scan_type directly
222+
if test_raw.type == self.scan_type:
223+
expected_test_type_name = self.scan_type
224+
else:
225+
expected_test_type_name = f"{test_raw.type} Scan"
226+
if expected_test_type_name != self.scan_type:
227+
expected_test_type_name = f"{expected_test_type_name} ({self.scan_type})"
228+
# Compare with existing test's test_type name
229+
if self.test.test_type.name != expected_test_type_name:
230+
msg = (
231+
f"Test type mismatch: Test {self.test.id} has test_type '{self.test.test_type.name}', "
232+
f"but the report contains test_type '{expected_test_type_name}'. "
233+
f"Reimport with matching test_type or create a new test."
234+
)
235+
raise ValidationError(msg)
212236
# This part change the name of the Test
213237
# we get it from the data of the parser
214238
# Update the test and test type with meta from the raw test

dojo/importers/default_importer.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
Test_Import,
1919
)
2020
from dojo.notifications.helper import create_notification
21-
from dojo.utils import perform_product_grading
21+
from dojo.utils import get_full_url, perform_product_grading
2222
from dojo.validators import clean_tags
2323

2424
logger = logging.getLogger(__name__)
@@ -365,11 +365,13 @@ def close_old_findings(
365365
old_findings = old_findings.filter(Q(service__isnull=True) | Q(service__exact=""))
366366
# Update the status of the findings and any endpoints
367367
for old_finding in old_findings:
368+
url = str(get_full_url(reverse("view_test", args=(self.test.id,))))
369+
test_title = str(self.test.title)
368370
self.mitigate_finding(
369371
old_finding,
370372
(
371-
"This finding has been automatically closed "
372-
"as it is not present anymore in recent scans."
373+
'This Finding has been automatically closed by the Test: \n "' + test_title + '"\n' + url +
374+
"\n\nThis is because this Finding is not present anymore in recent scans."
373375
),
374376
finding_groups_enabled=self.findings_groups_enabled,
375377
product_grading_option=False,

0 commit comments

Comments
 (0)