Skip to content

Commit a097be5

Browse files
Merge remote-tracking branch 'upstream/dev' into pghistory-for-real
2 parents f92d9ec + 6618b2b commit a097be5

File tree

13 files changed

+134
-61
lines changed

13 files changed

+134
-61
lines changed

components/node_modules/.gitkeep

Whitespace-only changes.

docs/content/en/open_source/upgrading/2.54.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: 'Upgrading to DefectDojo Version 2.54.x'
33
toc_hide: true
44
weight: -20251201
5-
description: Removal of django-auditlog and exclusive use of django-pghistory for audit logging.
5+
description: Removal of django-auditlog and exclusive use of django-pghistory for audit logging & Dropped support for DD_PARSER_EXCLUDE
66
---
77

88
## Breaking Change: Removal of django-auditlog
@@ -39,4 +39,9 @@ The switch to `django-pghistory` provides several advantages:
3939

4040
The backfill migration is not mandatory to succeed. If it fails for some reason, the only side effect will be that the first auditlog diff will contain all fields of an object instead just the changed fields.
4141

42+
## Dropped support for DD_PARSER_EXCLUDE
43+
44+
To simplify the management of the DefectDojo application, parser exclusions are no longer controlled via the environment variable DD_PARSER_EXCLUDE or application settings. This variable is now unsupported.
45+
From now on, you should use the active flag in the Test_Type model to enable or disable parsers. Only parsers associated with active Test_Type entries will be available for use.
46+
4247
Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.54.0) for the contents of the release.

docs/content/en/working_with_findings/findings_workflows/risk_acceptances.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ Any Findings associated with a Full Risk Acceptance will be set to **Inactive**,
2525

2626
Generally, any Risk Acceptances should follow your internal security policy and be re\-examined at an appropriate time. As a result, Risk Acceptances also have expiration dates. Once a Risk Acceptance expires, any Findings will be set to Active again.
2727

28+
### DefectDojo Pro vs Open Source: Cross-Product Risk Acceptances
29+
30+
**DefectDojo Pro** provides enhanced Risk Acceptance capabilities that aid in managing risk decisions at scale:
31+
32+
* **Cross-Product Risk Acceptances**: In DefectDojo Pro, you can apply a single Risk Acceptance across multiple Products. For example, if CVE-2024-1234 appears in 10 different products, you can create one Risk Acceptance that governs all instances of that CVE across your entire portfolio.
33+
* **Bulk CVE Management**: Search for all Findings with a specific CVE or vulnerability ID, then apply a Risk Acceptance to all instances simultaneously, regardless of which Product they belong to.
34+
35+
**DefectDojo Open Source** implements Risk Acceptances at the Engagement level:
36+
37+
* **Product-Scoped Risk Acceptances**: Risk Acceptances are restricted to individual Products. If CVE-2024-1234 appears in 10 different products, you need to create 10 separate Risk Acceptances—one for each Engagement.
38+
39+
Both approaches follow the same Risk Acceptance workflow described below, but the scope differs based on your DefectDojo edition.
40+
2841
### Add a new Full Risk Acceptance
2942

3043
Risk Acceptances can be added to a Finding in two ways:

dojo/filters.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
from dojo.risk_acceptance.queries import get_authorized_risk_acceptances
9494
from dojo.test.queries import get_authorized_tests
9595
from dojo.user.queries import get_authorized_users
96-
from dojo.utils import get_system_setting, is_finding_groups_enabled, truncate_timezone_aware
96+
from dojo.utils import get_system_setting, get_visible_scan_types, is_finding_groups_enabled, truncate_timezone_aware
9797

9898
logger = logging.getLogger(__name__)
9999

@@ -2030,6 +2030,9 @@ def __init__(self, *args, **kwargs):
20302030
# Don't show the product filter on the product finding view
20312031
self.set_related_object_fields(*args, **kwargs)
20322032

2033+
if "test__test_type" in self.form.fields:
2034+
self.form.fields["test__test_type"].queryset = get_visible_scan_types()
2035+
20332036
def set_related_object_fields(self, *args: list, **kwargs: dict):
20342037
finding_group_query = Finding_Group.objects.all()
20352038
if self.pid is not None:

dojo/finding/views.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
get_page_items_and_count,
119119
get_return_url,
120120
get_system_setting,
121+
get_visible_scan_types,
121122
get_words_for_field,
122123
match_finding_to_existing_findings,
123124
process_tag_notifications,
@@ -302,6 +303,7 @@ def get_initial_context(self, request: HttpRequest):
302303
"enable_table_filtering": get_system_setting("enable_ui_table_based_searching"),
303304
"title_words": get_words_for_field(Finding, "title"),
304305
"component_words": get_words_for_field(Finding, "component_name"),
306+
"visible_test_types": get_visible_scan_types(),
305307
}
306308
# Look to see if the product was used
307309
if product_id := self.get_product_id():

dojo/settings/settings.dist.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,6 @@
275275
# regular expression to exclude one or more parsers
276276
# could be usefull to limit parser allowed
277277
# AWS Scout2 Scan Parser is deprecated (see https://github.com/DefectDojo/django-DefectDojo/pull/5268)
278-
DD_PARSER_EXCLUDE=(str, ""),
279278
# when enabled in sytem settings, every minute a job run to delete excess duplicates
280279
# we limit the amount of duplicates that can be deleted in a single run of that job
281280
# to prevent overlapping runs of that job from occurrring
@@ -1849,9 +1848,6 @@ def saml2_attrib_map_format(din):
18491848
# If using this, lines for Qualys WAS deduplication functions must be un-commented
18501849
QUALYS_WAS_UNIQUE_ID = False
18511850

1852-
# exclusion list for parsers
1853-
PARSER_EXCLUDE = env("DD_PARSER_EXCLUDE")
1854-
18551851
SERIALIZATION_MODULES = {
18561852
"xml": "tagulous.serializers.xml_serializer",
18571853
"json": "tagulous.serializers.json",

dojo/tools/dependency_check/parser.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def add_finding(self, finding, dupes):
8787
def get_filename_and_path_from_dependency(
8888
self, dependency, related_dependency, namespace,
8989
):
90-
if not related_dependency:
90+
if related_dependency is None:
9191
return dependency.findtext(
9292
f"{namespace}fileName",
9393
), dependency.findtext(f"{namespace}filePath")
@@ -105,10 +105,10 @@ def get_component_name_and_version_from_dependency(
105105
self, dependency, related_dependency, namespace,
106106
):
107107
identifiers_node = dependency.find(namespace + "identifiers")
108-
if identifiers_node:
108+
if identifiers_node is not None:
109109
# analyzing identifier from the more generic to
110110
package_node = identifiers_node.find(".//" + namespace + "package")
111-
if package_node:
111+
if package_node is not None:
112112
pck_id = package_node.findtext(f"{namespace}id")
113113
purl = PackageURL.from_string(pck_id)
114114
purl_parts = purl.to_dict()
@@ -166,7 +166,7 @@ def get_component_name_and_version_from_dependency(
166166
maven_node = identifiers_node.find(
167167
".//" + namespace + 'identifier[@type="maven"]',
168168
)
169-
if maven_node:
169+
if maven_node is not None:
170170
maven_parts = maven_node.findtext(f"{namespace}name").split(
171171
":",
172172
)
@@ -181,7 +181,7 @@ def get_component_name_and_version_from_dependency(
181181
evidence_collected_node = dependency.find(
182182
namespace + "evidenceCollected",
183183
)
184-
if evidence_collected_node:
184+
if evidence_collected_node is not None:
185185
# <evidenceCollected>
186186
# <evidence type="product" confidence="HIGH">
187187
# <source>file</source>
@@ -199,12 +199,12 @@ def get_component_name_and_version_from_dependency(
199199
product_node = evidence_collected_node.find(
200200
".//" + namespace + 'evidence[@type="product"]',
201201
)
202-
if product_node:
202+
if product_node is not None:
203203
component_name = product_node.findtext(f"{namespace}value")
204204
version_node = evidence_collected_node.find(
205205
".//" + namespace + 'evidence[@type="version"]',
206206
)
207-
if version_node:
207+
if version_node is not None:
208208
component_version = version_node.findtext(
209209
f"{namespace}value",
210210
)
@@ -280,7 +280,7 @@ def get_finding_from_vulnerability(
280280
mitigated = None
281281
is_Mitigated = False
282282
name = vulnerability.findtext(f"{namespace}name")
283-
if vulnerability.find(f"{namespace}cwes"):
283+
if vulnerability.find(f"{namespace}cwes") is not None:
284284
cwe_field = vulnerability.find(f"{namespace}cwes").findtext(
285285
f"{namespace}cwe",
286286
)
@@ -425,14 +425,14 @@ def get_findings(self, filename, test):
425425

426426
dependencies = scan.find(namespace + "dependencies")
427427
scan_date = None
428-
if scan.find(f"{namespace}projectInfo"):
428+
if scan.find(f"{namespace}projectInfo") is not None:
429429
projectInfo_node = scan.find(f"{namespace}projectInfo")
430430
if projectInfo_node.findtext(f"{namespace}reportDate"):
431431
scan_date = dateutil.parser.parse(
432432
projectInfo_node.findtext(f"{namespace}reportDate"),
433433
)
434434

435-
if dependencies:
435+
if dependencies is not None:
436436
for dependency in dependencies.findall(namespace + "dependency"):
437437
vulnerabilities = dependency.find(
438438
namespace + "vulnerabilities",
@@ -441,7 +441,7 @@ def get_findings(self, filename, test):
441441
for vulnerability in vulnerabilities.findall(
442442
namespace + "vulnerability",
443443
):
444-
if vulnerability:
444+
if vulnerability is not None:
445445
finding = self.get_finding_from_vulnerability(
446446
dependency,
447447
None,
@@ -456,7 +456,7 @@ def get_findings(self, filename, test):
456456
relatedDependencies = dependency.find(
457457
namespace + "relatedDependencies",
458458
)
459-
if relatedDependencies:
459+
if relatedDependencies is not None:
460460
for (
461461
relatedDependency
462462
) in relatedDependencies.findall(
@@ -479,7 +479,7 @@ def get_findings(self, filename, test):
479479
for suppressedVulnerability in vulnerabilities.findall(
480480
namespace + "suppressedVulnerability",
481481
):
482-
if suppressedVulnerability:
482+
if suppressedVulnerability is not None:
483483
finding = self.get_finding_from_vulnerability(
484484
dependency,
485485
None,

dojo/tools/factory.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
from inspect import isclass
77
from pathlib import Path
88

9-
from django.conf import settings
10-
119
from dojo.models import Test_Type, Tool_Configuration, Tool_Type
1210

1311
PARSERS = {}
@@ -37,12 +35,12 @@ def get_parser(scan_type):
3735
if scan_type not in PARSERS:
3836
msg = f"Parser '{scan_type}' does not exist"
3937
raise ValueError(msg)
40-
rg = re.compile(settings.PARSER_EXCLUDE)
41-
if not rg.match(scan_type) or not settings.PARSER_EXCLUDE.strip():
42-
# update DB dynamically
43-
test_type, _ = Test_Type.objects.get_or_create(name=scan_type)
44-
if test_type.active:
45-
return PARSERS[scan_type]
38+
39+
# update DB dynamically
40+
test_type, _ = Test_Type.objects.get_or_create(name=scan_type)
41+
if test_type.active:
42+
return PARSERS[scan_type]
43+
4644
msg = f"Parser {scan_type} is not active"
4745
raise ValueError(msg)
4846

dojo/tools/fortify/xml_parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def xml_structure_before_24_2(self, root, test):
8686
for group in ReportSection.iter("GroupingSection"):
8787
title = group.findtext("groupTitle")
8888
maj_attr_summary = group.find("MajorAttributeSummary")
89-
if maj_attr_summary:
89+
if maj_attr_summary is not None:
9090
meta_info = maj_attr_summary.findall("MetaInfo")
9191
meta_pair[place][title] = {
9292
x.findtext("Name"): x.findtext("Value")
@@ -115,11 +115,11 @@ def xml_structure_before_24_2(self, root, test):
115115
"FilePath": issue.find("Primary").find("FilePath").text,
116116
"LineStart": issue.find("Primary").find("LineStart").text,
117117
}
118-
if issue.find("Primary").find("Snippet"):
118+
if issue.find("Primary").find("Snippet") is not None:
119119
details["Snippet"] = issue.find("Primary").find("Snippet").text
120120
else:
121121
details["Snippet"] = "n/a"
122-
if issue.find("Source"):
122+
if issue.find("Source") is not None:
123123
source = {
124124
"FileName": issue.find("Source").find("FileName").text,
125125
"FilePath": issue.find("Source").find("FilePath").text,

dojo/tools/nmap/parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ def get_findings(self, file, test):
9696
)
9797
description += service_info
9898
script_id = None
99-
if script := port_element.find("script"):
99+
script = port_element.find("script")
100+
if script is not None:
100101
if script_id := script.attrib.get("id"):
101102
description += f"**Script ID:** {script_id}\n"
102103
if script_output := script.attrib.get("output"):

0 commit comments

Comments
 (0)