Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release: Merge release into master from: release/2.40.3 #11322

Merged
merged 12 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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