Skip to content

Commit 4527392

Browse files
authored
Merge pull request #13275 from DefectDojo/release/2.50.4
Release: Merge release into master from: release/2.50.4
2 parents 15141de + 3480313 commit 4527392

File tree

14 files changed

+319
-130
lines changed

14 files changed

+319
-130
lines changed

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.50.3",
3+
"version": "2.50.4",
44
"license" : "BSD-3-Clause",
55
"private": true,
66
"dependencies": {

docs/content/en/changelog/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ For Open Source release notes, please see the [Releases page on GitHub](https://
1010

1111
## Sept 2025: v2.50
1212

13+
### Sept 15, 2025: v2.50.3
14+
15+
* **(Pro UI)** Added support for [CVSSv4.0](https://www.first.org/cvss/v4-0/) vector strings.
16+
1317
### Sept 15, 2025: v2.50.2
1418

1519
* **(Pro UI)** Added Any/All status filtering. Filtering by status allows you to apply either AND (inner join) logic, or OR (outer join) logic to the filter.

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.50.3"
7+
__version__ = "2.50.4"
88
__url__ = "https://github.com/DefectDojo/django-DefectDojo"
99
__docs__ = "https://documentation.defectdojo.com"

dojo/forms.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,6 @@ class ProductForm(forms.ModelForm):
342342
product_manager = forms.ModelChoiceField(queryset=Dojo_User.objects.exclude(is_active=False).order_by("first_name", "last_name"), required=False)
343343
technical_contact = forms.ModelChoiceField(queryset=Dojo_User.objects.exclude(is_active=False).order_by("first_name", "last_name"), required=False)
344344
team_manager = forms.ModelChoiceField(queryset=Dojo_User.objects.exclude(is_active=False).order_by("first_name", "last_name"), required=False)
345-
tags = TagField(
346-
required=False,
347-
help_text="Add tags that help describe this product. Choose from the list or add new tags. Press Enter key to add.",
348-
)
349345

350346
def __init__(self, *args, **kwargs):
351347
super().__init__(*args, **kwargs)
@@ -1017,10 +1013,6 @@ class EngForm(forms.ModelForm):
10171013
queryset=None,
10181014
required=True, label="Testing Lead")
10191015
test_strategy = forms.URLField(required=False, label="Test Strategy URL")
1020-
tags = TagField(
1021-
required=False,
1022-
help_text="Add tags that help describe this engagement. Choose from the list or add new tags. Press Enter key to add.",
1023-
)
10241016

10251017
def __init__(self, *args, **kwargs):
10261018
cicd = False
@@ -1103,10 +1095,6 @@ class TestForm(forms.ModelForm):
11031095
lead = forms.ModelChoiceField(
11041096
queryset=None,
11051097
required=False, label="Testing Lead")
1106-
tags = TagField(
1107-
required=False,
1108-
help_text="Add tags that help describe this test. Choose from the list or add new tags. Press Enter key to add.",
1109-
)
11101098

11111099
def __init__(self, *args, **kwargs):
11121100
obj = None
@@ -1463,10 +1451,6 @@ class FindingForm(forms.ModelForm):
14631451
choices=EFFORT_FOR_FIXING_CHOICES,
14641452
error_messages={
14651453
"invalid_choice": EFFORT_FOR_FIXING_INVALID_CHOICE})
1466-
tags = TagField(
1467-
required=False,
1468-
help_text="Add tags that help describe this finding. Choose from the list or add new tags. Press Enter key to add.",
1469-
)
14701454

14711455
# the only reliable way without hacking internal fields to get predicatble ordering is to make it explicit
14721456
field_order = ("title", "group", "date", "sla_start_date", "sla_expiration_date", "cwe", "vulnerability_ids", "severity", "cvss_info", "cvssv3",
@@ -1738,11 +1722,6 @@ class Meta:
17381722

17391723

17401724
class EditEndpointForm(forms.ModelForm):
1741-
tags = TagField(
1742-
required=False,
1743-
help_text="Add tags that help describe this endpoint. Choose from the list or add new tags. Press Enter key to add.",
1744-
)
1745-
17461725
class Meta:
17471726
model = Endpoint
17481727
exclude = ["product", "inherited_tags"]

dojo/jira_link/helper.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,14 +1401,16 @@ def update_epic(engagement, **kwargs):
14011401
jira = get_jira_connection(jira_instance)
14021402
j_issue = get_jira_issue(engagement)
14031403
issue = jira.issue(j_issue.jira_id)
1404-
14051404
epic_name = kwargs.get("epic_name")
14061405
if not epic_name:
14071406
epic_name = engagement.name
1408-
1407+
description = epic_name
1408+
branch_tag = engagement.branch_tag
1409+
if branch_tag:
1410+
description += "\nBranch: " + branch_tag
14091411
jira_issue_update_kwargs = {
14101412
"summary": epic_name,
1411-
"description": epic_name,
1413+
"description": description,
14121414
}
14131415
if (epic_priority := kwargs.get("epic_priority")) is not None:
14141416
jira_issue_update_kwargs["priority"] = {"name": epic_priority}
@@ -1443,12 +1445,16 @@ def add_epic(engagement, **kwargs):
14431445
epic_issue_type_name = getattr(jira_project, "epic_issue_type_name", "Epic")
14441446
if not epic_name:
14451447
epic_name = engagement.name
1448+
description = epic_name
1449+
branch_tag = engagement.branch_tag
1450+
if branch_tag:
1451+
description += "\nBranch: " + branch_tag
14461452
issue_dict = {
14471453
"project": {
14481454
"key": jira_project.project_key,
14491455
},
14501456
"summary": epic_name,
1451-
"description": epic_name,
1457+
"description": description,
14521458
"issuetype": {
14531459
"name": epic_issue_type_name,
14541460
},

dojo/tools/api_sonarqube/api_client.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,31 @@ def get_hotspot_rule(self, rule_id):
334334
self.rules_cache.update({rule_id: rule})
335335
return rule
336336

337+
def get_hotspot(self, rule_id):
338+
"""
339+
Get detailed information about a hotspot
340+
:param rule_id:
341+
:return:
342+
"""
343+
rule = self.rules_cache.get(rule_id)
344+
if not rule:
345+
response = self.session.get(
346+
url=f"{self.sonar_api_url}/hotspots/search",
347+
params={"hotspots": rule_id},
348+
headers=self.default_headers,
349+
timeout=settings.REQUESTS_TIMEOUT,
350+
)
351+
if not response.ok:
352+
msg = (
353+
f"Unable to get the hotspot rule {rule_id} "
354+
f"due to {response.status_code} - {response.content}"
355+
)
356+
raise Exception(msg)
357+
358+
rule = response.json()["hotspots"][0]
359+
self.rules_cache.update({rule_id: rule})
360+
return rule
361+
337362
def transition_issue(self, issue_key, transition):
338363
"""
339364
Do workflow transition on an issue. Requires authentication and Browse permission on project.
@@ -375,6 +400,46 @@ def transition_issue(self, issue_key, transition):
375400
)
376401
raise Exception(msg)
377402

403+
def transition_hotspot(self, issue_key, status, resolution=None):
404+
"""
405+
Do workflow transition on an issue. Requires authentication and Browse permission on project.
406+
The transitions 'wontfix' and 'falsepositive' require the permission 'Administer Issues'.
407+
The transitions involving security hotspots (except 'requestreview') require
408+
the permission 'Administer Security Hotspot'.
409+
410+
Possible resolution values:
411+
- FIXED
412+
- SAFE
413+
- ACKNOWLEDGED
414+
415+
Possible status values:
416+
- TO_REVIEW
417+
- REVIEWED
418+
419+
:param issue_key:
420+
:param status:
421+
:param resolution:
422+
:return:
423+
"""
424+
data = {"hotspot": issue_key, "status": status}
425+
426+
if resolution:
427+
data["resolution"] = resolution
428+
429+
response = self.session.post(
430+
url=f"{self.sonar_api_url}/hotspots/change_status",
431+
data=data,
432+
headers=self.default_headers,
433+
timeout=settings.REQUESTS_TIMEOUT,
434+
)
435+
436+
if not response.ok:
437+
msg = (
438+
f"Unable to change status {status} / resolution {resolution} the issue {issue_key} "
439+
f'due to {response.status_code} - {response.content.decode("utf-8")}'
440+
)
441+
raise Exception(msg)
442+
378443
def add_comment(self, issue_key, text):
379444
"""
380445
Add a comment.

0 commit comments

Comments
 (0)