Skip to content

Commit

Permalink
Merge pull request #11322 from DefectDojo/release/2.40.3
Browse files Browse the repository at this point in the history
Release: Merge release into master from: release/2.40.3
  • Loading branch information
rossops authored Nov 25, 2024
2 parents 8b20fa0 + 273c318 commit 6d847ab
Show file tree
Hide file tree
Showing 25 changed files with 521 additions and 57 deletions.
2 changes: 1 addition & 1 deletion components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "defectdojo",
"version": "2.40.2",
"version": "2.40.3",
"license" : "BSD-3-Clause",
"private": true,
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion dojo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
# Django starts so that shared_task will use this app.
from .celery import app as celery_app # noqa: F401

__version__ = "2.40.2"
__version__ = "2.40.3"
__url__ = "https://github.com/DefectDojo/django-DefectDojo"
__docs__ = "https://documentation.defectdojo.com"
5 changes: 3 additions & 2 deletions dojo/api_v2/serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import collections
import json
import logging
import re
Expand Down Expand Up @@ -280,10 +281,10 @@ def _pop_tags(self, validated_data):
return (to_be_tagged, validated_data)


class RequestResponseDict(list):
class RequestResponseDict(collections.UserList):
def __init__(self, *args, **kwargs):
pretty_print = kwargs.pop("pretty_print", True)
list.__init__(self, *args, **kwargs)
collections.UserList.__init__(self, *args, **kwargs)
self.pretty_print = pretty_print

def __add__(self, rhs):
Expand Down
3 changes: 2 additions & 1 deletion dojo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4613,7 +4613,7 @@ def __str__(self):
auditlog.register(Dojo_User, exclude_fields=["password"])
auditlog.register(Endpoint)
auditlog.register(Engagement)
auditlog.register(Finding)
auditlog.register(Finding, m2m_fields={"reviewers"})
auditlog.register(Finding_Group)
auditlog.register(Product_Type)
auditlog.register(Product)
Expand All @@ -4623,6 +4623,7 @@ def __str__(self):
auditlog.register(Cred_User, exclude_fields=["password"])
auditlog.register(Notification_Webhooks, exclude_fields=["header_name", "header_value"])


from dojo.utils import calculate_grade, to_str_typed # noqa: E402 # there is issue due to a circular import

tagulous.admin.register(Product.tags)
Expand Down
2 changes: 1 addition & 1 deletion dojo/settings/.settings.dist.py.sha256sum
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f85484f23e59aabe591b30db10e0de05aaeeb9d8979d236d565dc8279e03e116
93f0a72eaae484814b5b38dba8dc57d529ea3c414b7fa4da8b2e347851dba46e
3 changes: 2 additions & 1 deletion dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,7 @@ def saml2_attrib_map_format(dict):
"Dependency Check Scan": ["title", "cwe", "file_path"],
"Dockle Scan": ["title", "description", "vuln_id_from_tool"],
"Dependency Track Finding Packaging Format (FPF) Export": ["component_name", "component_version", "vulnerability_ids"],
"Mobsfscan Scan": ["title", "severity", "cwe"],
"Mobsfscan Scan": ["title", "severity", "cwe", "file_path", "description"],
"Tenable Scan": ["title", "severity", "vulnerability_ids", "cwe", "description"],
"Nexpose Scan": ["title", "severity", "vulnerability_ids", "cwe"],
# possible improvement: in the scanner put the library name into file_path, then dedup on cwe + file_path + severity
Expand Down Expand Up @@ -1768,6 +1768,7 @@ def saml2_attrib_map_format(dict):
"TEMP": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/TEMP-0841856-B18BAF
"DSA": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/DSA-5791-1
"RLSA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RLSA-2024:7001
"RLBA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RLBA-2024:6968
}
# List of acceptable file types that can be uploaded to a given object via arbitrary file upload
FILE_UPLOAD_TYPES = env("DD_FILE_UPLOAD_TYPES")
Expand Down
5 changes: 4 additions & 1 deletion dojo/templatetags/display_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,10 @@ def action_log_entry(value, autoescape=None):
history = json.loads(value)
text = ""
for k in history.keys():
text += k.capitalize() + ' changed from "' + \
if isinstance(history[k], dict):
text += k.capitalize() + " operation: " + history[k].get("operation", "unknown") + ": " + str(history[k].get("objects", "unknown"))
else:
text += k.capitalize() + ' changed from "' + \
history[k][0] + '" to "' + history[k][1] + '"\n'
return text

Expand Down
29 changes: 24 additions & 5 deletions dojo/tools/anchorectl_policies/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_findings(self, filename, test):
image_name = result["tag"]
trigger_id = result["triggerId"]
repo, tag = image_name.split(":", 2)
severity = map_gate_action_to_severity(status)
severity, active = get_severity(status, description)
vulnerability_id = extract_vulnerability_id(trigger_id)
title = (
policy_id
Expand All @@ -54,6 +54,7 @@ def get_findings(self, filename, test):
test=test,
description=description,
severity=severity,
active=active,
references=f"Policy ID: {policy_id}\nTrigger ID: {trigger_id}",
file_path=search_filepath(description),
component_name=repo,
Expand All @@ -77,14 +78,32 @@ def get_findings(self, filename, test):
return items


def map_gate_action_to_severity(gate):
def map_gate_action_to_severity(status):
gate_action_to_severity = {
"stop": "Critical",
"warn": "Medium",
}
if gate in gate_action_to_severity:
return gate_action_to_severity[gate]
return "Low"
if status in gate_action_to_severity:
return gate_action_to_severity[status], True

return "Low", True


def get_severity(status, description):
parsed_severity = description.split()[0]
valid_severities = ["LOW", "INFO", "UNKNOWN", "CRITICAL", "MEDIUM"]
if parsed_severity in valid_severities:
severity = "Info"
if parsed_severity == "UNKNOWN":
severity = "Info"
elif status != "go":
severity = parsed_severity.lower().capitalize()

active = False if status == "go" else True

return severity, active

return map_gate_action_to_severity(status)


def policy_name(policies, policy_id):
Expand Down
9 changes: 9 additions & 0 deletions dojo/tools/checkmarx_one/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ def get_results_sast(
description = vulnerability.get("description")
file_path = vulnerability.get("data").get("nodes")[0].get("fileName")
unique_id_from_tool = vulnerability.get("id", vulnerability.get("similarityId"))
if description is None:
description = vulnerability.get("severity").title() + " " + vulnerability.get("data").get("queryName").replace("_", " ")

return Finding(
description=description,
title=description,
Expand All @@ -280,6 +283,9 @@ def get_results_kics(
description = vulnerability.get("description")
file_path = vulnerability.get("data").get("filename", vulnerability.get("data").get("fileName"))
unique_id_from_tool = vulnerability.get("id", vulnerability.get("similarityId"))
if description is None:
description = vulnerability.get("severity").title() + " " + vulnerability.get("data").get("queryName").replace("_", " ")

return Finding(
title=description,
description=description,
Expand All @@ -298,6 +304,9 @@ def get_results_sca(
) -> Finding:
description = vulnerability.get("description")
unique_id_from_tool = vulnerability.get("id", vulnerability.get("similarityId"))
if description is None:
description = vulnerability.get("severity").title() + " " + vulnerability.get("data").get("queryName").replace("_", " ")

finding = Finding(
title=description,
description=description,
Expand Down
52 changes: 33 additions & 19 deletions dojo/tools/mobsfscan/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,43 @@ def get_findings(self, filename, test):
else:
severity = "Info"

finding = Finding(
title=f"{key}",
test=test,
severity=severity,
nb_occurences=1,
cwe=cwe,
description=description,
references=references,
)
files = []

if item.get("files"):
for file in item.get("files"):
file_path = file.get("file_path")
line = file.get("match_lines")[0]
file_path = file.get("file_path", "")
line = file.get("match_lines", [0])[0]
snippet = file.get("match_string", "")

files.append((file_path, line, snippet))
else:
files.append(("", 0, ""))

for file_path, line, snippet in files:

finding = Finding(
title=f"{key}",
test=test,
severity=severity,
nb_occurences=1,
cwe=cwe,
description=description,
references=references,
)

if file_path:
finding.file_path = file_path
finding.line = line
finding.description = f"{description}\n**Snippet:** `{snippet}`"

dupe_key = hashlib.sha256(
(key + str(cwe) + masvs + owasp_mobile).encode("utf-8"),
).hexdigest()
dupe_key = hashlib.sha256(
(key + str(cwe) + masvs + owasp_mobile + file_path).encode("utf-8"),
).hexdigest()

if dupe_key in dupes:
finding = dupes[dupe_key]
finding.nb_occurences += 1
else:
dupes[dupe_key] = finding

if dupe_key in dupes:
finding = dupes[dupe_key]
finding.nb_occurences += 1
else:
dupes[dupe_key] = finding
return list(dupes.values())
3 changes: 2 additions & 1 deletion dojo/tools/trivy_operator/checks_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ def handle_checks(self, labels, checks, test):
static_finding=True,
dynamic_finding=False,
service=service,
tags=[resource_namespace],
)
if resource_namespace != "":
finding.tags = resource_namespace
if check_id:
finding.unsaved_vulnerability_ids = [UniformTrivyVulnID().return_uniformed_vulnid(check_id)]
findings.append(finding)
Expand Down
45 changes: 45 additions & 0 deletions dojo/tools/trivy_operator/clustercompliance_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from dojo.models import Finding

TRIVY_SEVERITIES = {
"CRITICAL": "Critical",
"HIGH": "High",
"MEDIUM": "Medium",
"LOW": "Low",
"UNKNOWN": "Info",
}


class TrivyClusterComplianceHandler:
def handle_clustercompliance(self, controls, clustercompliance, test):
findings = []
for result in clustercompliance.get("controlCheck"):
if int(result.get("totalFail", 0)) > 0:
description = ""
result_id = result.get("id", "")
vulnerabilityids = []
for control in controls:
if control.get("id") == result_id:
vulnids = control.get("checks", [])
for vulnid in vulnids:
vulnerabilityids.append(vulnid.get("id"))
description += "**description:** " + control.get("description") + "\n"
result_name = result.get("name", "")
result_severity = result.get("severity", "")
result_totalfail = str(result.get("totalFail", ""))
severity = TRIVY_SEVERITIES[result_severity]
description += "**id:** " + result_id + "\n"
description += "**name:** " + result_name + "\n"
description += "**totalfail:** " + result_totalfail + "\n"
title = "TrivyClusterCompliance " + result_id + " totalFail: " + result_totalfail
finding = Finding(
test=test,
title=title,
description=description,
severity=severity,
static_finding=False,
dynamic_finding=True,
)
if vulnerabilityids != []:
finding.unsaved_vulnerability_ids = vulnerabilityids
findings.append(finding)
return findings
17 changes: 11 additions & 6 deletions dojo/tools/trivy_operator/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json

from dojo.tools.trivy_operator.checks_handler import TrivyChecksHandler
from dojo.tools.trivy_operator.clustercompliance_handler import TrivyClusterComplianceHandler
from dojo.tools.trivy_operator.compliance_handler import TrivyComplianceHandler
from dojo.tools.trivy_operator.secrets_handler import TrivySecretsHandler
from dojo.tools.trivy_operator.vulnerability_handler import TrivyVulnerabilityHandler
Expand Down Expand Up @@ -38,6 +39,7 @@ def get_findings(self, scan_file, test):
return findings

def output_findings(self, data, test):
findings = []
if data is None:
return []
metadata = data.get("metadata", None)
Expand All @@ -47,10 +49,6 @@ def output_findings(self, data, test):
if labels is None:
return []
report = data.get("report", None)
benchmark = data.get("status", None)
if benchmark is not None:
benchmarkreport = benchmark.get("detailReport", None)
findings = []
if report is not None:
vulnerabilities = report.get("vulnerabilities", None)
if vulnerabilities is not None:
Expand All @@ -61,6 +59,13 @@ def output_findings(self, data, test):
secrets = report.get("secrets", None)
if secrets is not None:
findings += TrivySecretsHandler().handle_secrets(labels, secrets, test)
elif benchmarkreport is not None:
findings += TrivyComplianceHandler().handle_compliance(benchmarkreport, test)
status = data.get("status", None)
if status is not None:
benchmarkreport = status.get("detailReport", None)
if benchmarkreport is not None:
findings += TrivyComplianceHandler().handle_compliance(benchmarkreport, test)
clustercompliance = status.get("summaryReport", None)
if clustercompliance is not None:
if int(status.get("summary").get("failCount", 0)) > 0:
findings += TrivyClusterComplianceHandler().handle_clustercompliance(controls=data.get("spec").get("compliance").get("controls"), clustercompliance=clustercompliance, test=test)
return findings
3 changes: 2 additions & 1 deletion dojo/tools/trivy_operator/secrets_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def handle_secrets(self, labels, secrets, test):
static_finding=True,
dynamic_finding=False,
service=service,
tags=[resource_namespace],
)
if resource_namespace != "":
finding.tags = resource_namespace
findings.append(finding)
return findings
2 changes: 1 addition & 1 deletion dojo/tools/trivy_operator/vulnerability_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def handle_vulns(self, labels, vulnerabilities, test):
dynamic_finding=False,
service=service,
file_path=file_path,
tags=finding_tags,
tags=[tag for tag in finding_tags if tag != ""],
)
if vuln_id:
finding.unsaved_vulnerability_ids = [UniformTrivyVulnID().return_uniformed_vulnid(vuln_id)]
Expand Down
4 changes: 2 additions & 2 deletions helm/defectdojo/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
apiVersion: v2
appVersion: "2.40.2"
appVersion: "2.40.3"
description: A Helm chart for Kubernetes to install DefectDojo
name: defectdojo
version: 1.6.160
version: 1.6.161
icon: https://www.defectdojo.org/img/favicon.ico
maintainers:
- name: madchap
Expand Down
5 changes: 0 additions & 5 deletions helm/defectdojo/templates/django-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,6 @@ spec:
- name: http-uwsgi
protocol: TCP
containerPort: 8081
{{- if .Values.django.uwsgi.enableDebug }}
- name: debug
protocol: TCP
containerPort: 3000
{{- end }}
envFrom:
- configMapRef:
name: {{ $fullName }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"detail": [
{
"description": "CRITICAL User root found as effective user, which is not on the allowed list",
"gate": "dockerfile",
"imageId": "d26f0119b9634091a541b081dd8bdca435ab52e114e4b4328575c0bc2c69768b",
"policyId": "RootUser",
"status": "warn",
"tag": "test/testimage:testtag",
"triggerId": "b2605c2ddbdb02b8e2365c9248dada5a",
"triggerName": "effective_user"
}
],
"digest": "sha256:8htz0bf942cfcd6hg8cf6435afd318b65d23e4c1a80044304c6e3ed20",
"finalAction": "stop",
"finalActionReason": "policy_evaluation",
"lastEvaluation": "2022-09-20T08:25:52Z",
"policyId": "9e104ade-7b57-4cdc-93fb-4949bf3b36b6",
"status": "fail",
"tag": "test/testimage:testtag"
}
]
Loading

0 comments on commit 6d847ab

Please sign in to comment.