From 71920725c25da2f287bdd92a861a4ef14253310e Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Fri, 23 May 2025 19:04:33 +0200 Subject: [PATCH 01/18] :hammer: Merge the MobSF scanner --- .../parsers/file/mobsf.md | 2 +- .../parsers/file/mobsfscan.md | 17 - dojo/tools/mobsf/api_report_json.py | 388 +++++++++++++++++ dojo/tools/mobsf/parser.py | 391 +----------------- .../{mobsfscan/parser.py => mobsf/report.py} | 17 +- dojo/tools/mobsfscan/__init__.py | 0 .../{mobsfscan => mobsf}/many_findings.json | 0 .../many_findings_cwe_lower.json | 0 .../{mobsfscan => mobsf}/no_findings.json | 0 unittests/tools/test_mobsf_parser.py | 159 +++++++ unittests/tools/test_mobsfscan_parser.py | 165 -------- 11 files changed, 558 insertions(+), 581 deletions(-) delete mode 100644 docs/content/en/connecting_your_tools/parsers/file/mobsfscan.md create mode 100644 dojo/tools/mobsf/api_report_json.py rename dojo/tools/{mobsfscan/parser.py => mobsf/report.py} (84%) delete mode 100644 dojo/tools/mobsfscan/__init__.py rename unittests/scans/{mobsfscan => mobsf}/many_findings.json (100%) rename unittests/scans/{mobsfscan => mobsf}/many_findings_cwe_lower.json (100%) rename unittests/scans/{mobsfscan => mobsf}/no_findings.json (100%) delete mode 100644 unittests/tools/test_mobsfscan_parser.py diff --git a/docs/content/en/connecting_your_tools/parsers/file/mobsf.md b/docs/content/en/connecting_your_tools/parsers/file/mobsf.md index 7bbbf564a0c..9d827b20df5 100644 --- a/docs/content/en/connecting_your_tools/parsers/file/mobsf.md +++ b/docs/content/en/connecting_your_tools/parsers/file/mobsf.md @@ -2,7 +2,7 @@ title: "MobSF Scanner" toc_hide: true --- -Export a JSON file using the API, api/v1/report\_json. +Export a JSON file using the API, api/v1/report\_json and import it to Defectdojo or import a JSON report from ### Sample Scan Data Sample MobSF Scanner scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/mobsf). diff --git a/docs/content/en/connecting_your_tools/parsers/file/mobsfscan.md b/docs/content/en/connecting_your_tools/parsers/file/mobsfscan.md deleted file mode 100644 index 2c39d114287..00000000000 --- a/docs/content/en/connecting_your_tools/parsers/file/mobsfscan.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "Mobsfscan" -toc_hide: true ---- -Import JSON report from - -### Sample Scan Data -Sample Mobsfscan scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/mobsfscan). - -### Default Deduplication Hashcode Fields -By default, DefectDojo identifies duplicate Findings using these [hashcode fields](https://docs.defectdojo.com/en/working_with_findings/finding_deduplication/about_deduplication/): - -- title -- severity -- cwe -- file path -- description diff --git a/dojo/tools/mobsf/api_report_json.py b/dojo/tools/mobsf/api_report_json.py new file mode 100644 index 00000000000..6f5bd1c6c75 --- /dev/null +++ b/dojo/tools/mobsf/api_report_json.py @@ -0,0 +1,388 @@ +from datetime import datetime + +from html2text import html2text + +from dojo.models import Finding + + +class MobSFapireport: + def get_findings(self, data, test): + dupes = {} + find_date = datetime.now() + + test_description = "" + if "name" in data: + test_description = "**Info:**\n" + if "packagename" in data: + test_description = "{} **Package Name:** {}\n".format(test_description, data["packagename"]) + + if "mainactivity" in data: + test_description = "{} **Main Activity:** {}\n".format(test_description, data["mainactivity"]) + + if "pltfm" in data: + test_description = "{} **Platform:** {}\n".format(test_description, data["pltfm"]) + + if "sdk" in data: + test_description = "{} **SDK:** {}\n".format(test_description, data["sdk"]) + + if "min" in data: + test_description = "{} **Min SDK:** {}\n".format(test_description, data["min"]) + + if "targetsdk" in data: + test_description = "{} **Target SDK:** {}\n".format(test_description, data["targetsdk"]) + + if "minsdk" in data: + test_description = "{} **Min SDK:** {}\n".format(test_description, data["minsdk"]) + + if "maxsdk" in data: + test_description = "{} **Max SDK:** {}\n".format(test_description, data["maxsdk"]) + + test_description = f"{test_description}\n**File Information:**\n" + + if "name" in data: + test_description = "{} **Name:** {}\n".format(test_description, data["name"]) + + if "md5" in data: + test_description = "{} **MD5:** {}\n".format(test_description, data["md5"]) + + if "sha1" in data: + test_description = "{} **SHA-1:** {}\n".format(test_description, data["sha1"]) + + if "sha256" in data: + test_description = "{} **SHA-256:** {}\n".format(test_description, data["sha256"]) + + if "size" in data: + test_description = "{} **Size:** {}\n".format(test_description, data["size"]) + + if "urls" in data: + curl = "" + for url in data["urls"]: + for durl in url["urls"]: + curl = f"{durl}\n" + + if curl: + test_description = f"{test_description}\n**URL's:**\n {curl}\n" + + if "bin_anal" in data: + test_description = "{} \n**Binary Analysis:** {}\n".format(test_description, data["bin_anal"]) + + test.description = html2text(test_description) + + mobsf_findings = [] + # Mobile Permissions + if "permissions" in data: + # for permission, details in data["permissions"].items(): + if isinstance(data["permissions"], list): + for details in data["permissions"]: + mobsf_item = { + "category": "Mobile Permissions", + "title": details.get("name", ""), + "severity": self.getSeverityForPermission(details.get("status")), + "description": "**Permission Type:** " + details.get("name", "") + " (" + details.get("status", "") + ")\n\n**Description:** " + details.get("description", "") + "\n\n**Reason:** " + details.get("reason", ""), + "file_path": None, + } + mobsf_findings.append(mobsf_item) + else: + for permission, details in list(data["permissions"].items()): + mobsf_item = { + "category": "Mobile Permissions", + "title": permission, + "severity": self.getSeverityForPermission(details.get("status", "")), + "description": "**Permission Type:** " + permission + "\n\n**Description:** " + details.get("description", ""), + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # Insecure Connections + if "insecure_connections" in data: + for details in data["insecure_connections"]: + insecure_urls = "" + for url in details.split(","): + insecure_urls = insecure_urls + url + "\n" + + mobsf_item = { + "category": None, + "title": "Insecure Connections", + "severity": "Low", + "description": insecure_urls, + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # Certificate Analysis + if "certificate_analysis" in data: + if data["certificate_analysis"] != {}: + certificate_info = data["certificate_analysis"]["certificate_info"] + for details in data["certificate_analysis"]["certificate_findings"]: + if len(details) == 3: + mobsf_item = { + "category": "Certificate Analysis", + "title": details[2], + "severity": details[0].title(), + "description": details[1] + "\n\n**Certificate Info:** " + certificate_info, + "file_path": None, + } + mobsf_findings.append(mobsf_item) + elif len(details) == 2: + mobsf_item = { + "category": "Certificate Analysis", + "title": details[1], + "severity": details[0].title(), + "description": details[1] + "\n\n**Certificate Info:** " + certificate_info, + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # Manifest Analysis + if "manifest_analysis" in data: + if data["manifest_analysis"] != {} and isinstance(data["manifest_analysis"], dict): + if data["manifest_analysis"]["manifest_findings"]: + for details in data["manifest_analysis"]["manifest_findings"]: + mobsf_item = { + "category": "Manifest Analysis", + "title": details["title"], + "severity": details["severity"].title(), + "description": details["description"] + "\n\n " + details["name"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + else: + for details in data["manifest_analysis"]: + mobsf_item = { + "category": "Manifest Analysis", + "title": details["title"], + "severity": details["stat"].title(), + "description": details["desc"] + "\n\n " + details["name"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # Code Analysis + if "code_analysis" in data: + if data["code_analysis"] != {}: + if data["code_analysis"].get("findings"): + for details in data["code_analysis"]["findings"]: + metadata = data["code_analysis"]["findings"][details] + mobsf_item = { + "category": "Code Analysis", + "title": details, + "severity": metadata["metadata"]["severity"].title(), + "description": metadata["metadata"]["description"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + else: + for details in data["code_analysis"]: + metadata = data["code_analysis"][details] + if metadata.get("metadata"): + mobsf_item = { + "category": "Code Analysis", + "title": details, + "severity": metadata["metadata"]["severity"].title(), + "description": metadata["metadata"]["description"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # Binary Analysis + if "binary_analysis" in data: + if isinstance(data["binary_analysis"], list): + for details in data["binary_analysis"]: + for binary_analysis_type in details: + if binary_analysis_type != "name": + mobsf_item = { + "category": "Binary Analysis", + "title": details[binary_analysis_type]["description"].split(".")[0], + "severity": details[binary_analysis_type]["severity"].title(), + "description": details[binary_analysis_type]["description"], + "file_path": details["name"], + } + mobsf_findings.append(mobsf_item) + elif data["binary_analysis"].get("findings"): + for details in data["binary_analysis"]["findings"].values(): + # "findings":{ + # "Binary makes use of insecure API(s)":{ + # "detailed_desc":"The binary may contain the following insecure API(s) _memcpy\n, _strlen\n", + # "severity":"high", + # "cvss":6, + # "cwe":"CWE-676: Use of Potentially Dangerous Function", + # "owasp-mobile":"M7: Client Code Quality", + # "masvs":"MSTG-CODE-8" + # }, + mobsf_item = { + "category": "Binary Analysis", + "title": details["detailed_desc"], + "severity": details["severity"].title(), + "description": details["detailed_desc"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + else: + for details in data["binary_analysis"].values(): + # "Binary makes use of insecure API(s)":{ + # "detailed_desc":"The binary may contain the following insecure API(s) _vsprintf.", + # "severity":"high", + # "cvss":6, + # "cwe":"CWE-676 - Use of Potentially Dangerous Function", + # "owasp-mobile":"M7: Client Code Quality", + # "masvs":"MSTG-CODE-8" + # } + mobsf_item = { + "category": "Binary Analysis", + "title": details["detailed_desc"], + "severity": details["severity"].title(), + "description": details["detailed_desc"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # specific node for Android reports + if "android_api" in data: + # "android_insecure_random": { + # "files": { + # "u/c/a/b/a/c.java": "9", + # "kotlinx/coroutines/repackaged/net/bytebuddy/utility/RandomString.java": "3", + # ... + # "hu/mycompany/vbnmqweq/gateway/msg/Response.java": "13" + # }, + # "metadata": { + # "id": "android_insecure_random", + # "description": "The App uses an insecure Random Number Generator.", + # "type": "Regex", + # "pattern": "java\\.util\\.Random;", + # "severity": "high", + # "input_case": "exact", + # "cvss": 7.5, + # "cwe": "CWE-330 Use of Insufficiently Random Values", + # "owasp-mobile": "M5: Insufficient Cryptography", + # "masvs": "MSTG-CRYPTO-6" + # } + # }, + for api, details in list(data["android_api"].items()): + mobsf_item = { + "category": "Android API", + "title": details["metadata"]["description"], + "severity": details["metadata"]["severity"].title(), + "description": "**API:** " + api + "\n\n**Description:** " + details["metadata"]["description"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # Manifest + if "manifest" in data: + for details in data["manifest"]: + mobsf_item = { + "category": "Manifest", + "title": details["title"], + "severity": details["stat"], + "description": details["desc"], + "file_path": None, + } + mobsf_findings.append(mobsf_item) + + # MobSF Findings + if "findings" in data: + for title, finding in list(data["findings"].items()): + description = title + file_path = None + + if "path" in finding: + description += "\n\n**Files:**\n" + for path in finding["path"]: + if file_path is None: + file_path = path + description = description + " * " + path + "\n" + + mobsf_item = { + "category": "Findings", + "title": title, + "severity": finding["level"], + "description": description, + "file_path": file_path, + } + + mobsf_findings.append(mobsf_item) + if isinstance(data, list): + for finding in data: + mobsf_item = { + "category": finding["category"], + "title": finding["name"], + "severity": finding["severity"], + "description": finding["description"] + "\n" + "**apk_exploit_dict:** " + str(finding["apk_exploit_dict"]) + "\n" + "**line_number:** " + str(finding["line_number"]), + "file_path": finding["file_object"], + } + mobsf_findings.append(mobsf_item) + for mobsf_finding in mobsf_findings: + title = mobsf_finding["title"] + sev = self.getCriticalityRating(mobsf_finding["severity"]) + description = "" + file_path = None + if mobsf_finding["category"]: + description += "**Category:** " + mobsf_finding["category"] + "\n\n" + description += html2text(mobsf_finding["description"]) + finding = Finding( + title=title, + cwe=919, # Weaknesses in Mobile Applications + test=test, + description=description, + severity=sev, + references=None, + date=find_date, + static_finding=True, + dynamic_finding=False, + nb_occurences=1, + ) + if mobsf_finding["file_path"]: + finding.file_path = mobsf_finding["file_path"] + dupe_key = sev + title + description + mobsf_finding["file_path"] + else: + dupe_key = sev + title + description + if mobsf_finding["category"]: + dupe_key += mobsf_finding["category"] + if dupe_key in dupes: + find = dupes[dupe_key] + if description is not None: + find.description += description + find.nb_occurences += 1 + else: + dupes[dupe_key] = finding + return list(dupes.values()) + + def getSeverityForPermission(self, status): + """ + Convert status for permission detection to severity + + In MobSF there is only 4 know values for permission, + we map them as this: + dangerous => High (Critical?) + normal => Info + signature => Info (it's positive so... Info) + signatureOrSystem => Info (it's positive so... Info) + """ + if status == "dangerous": + return "High" + return "Info" + + # Criticality rating + def getCriticalityRating(self, rating): + criticality = "Info" + if rating.lower() == "good": + criticality = "Info" + elif rating.lower() == "warning": + criticality = "Low" + elif rating.lower() == "vulnerability": + criticality = "Medium" + else: + criticality = rating.lower().capitalize() + return criticality + + def suite_data(self, suites): + suite_info = "" + suite_info += suites["name"] + "\n" + suite_info += "Cipher Strength: " + str(suites["cipherStrength"]) + "\n" + if "ecdhBits" in suites: + suite_info += "ecdhBits: " + str(suites["ecdhBits"]) + "\n" + if "ecdhStrength" in suites: + suite_info += "ecdhStrength: " + str(suites["ecdhStrength"]) + suite_info += "\n\n" + return suite_info diff --git a/dojo/tools/mobsf/parser.py b/dojo/tools/mobsf/parser.py index c61065ea892..d9e8b419aa0 100644 --- a/dojo/tools/mobsf/parser.py +++ b/dojo/tools/mobsf/parser.py @@ -1,10 +1,8 @@ import json -from datetime import datetime -from html2text import html2text - -from dojo.models import Finding +from dojo.tools.mobsf.api_report_json import MobSFapireport +from dojo.tools.mobsf.report import MobSFjsonreport class MobSFParser: @@ -16,7 +14,7 @@ def get_label_for_scan_types(self, scan_type): return "MobSF Scan" def get_description_for_scan_types(self, scan_type): - return "Export a JSON file using the API, api/v1/report_json." + return "Import JSON report from mobsfscan report file or from api/v1/report_json" def get_findings(self, filename, test): tree = filename.read() @@ -24,381 +22,8 @@ def get_findings(self, filename, test): data = json.loads(str(tree, "utf-8")) except: data = json.loads(tree) - find_date = datetime.now() - dupes = {} - test_description = "" - if "name" in data: - test_description = "**Info:**\n" - if "packagename" in data: - test_description = "{} **Package Name:** {}\n".format(test_description, data["packagename"]) - - if "mainactivity" in data: - test_description = "{} **Main Activity:** {}\n".format(test_description, data["mainactivity"]) - - if "pltfm" in data: - test_description = "{} **Platform:** {}\n".format(test_description, data["pltfm"]) - - if "sdk" in data: - test_description = "{} **SDK:** {}\n".format(test_description, data["sdk"]) - - if "min" in data: - test_description = "{} **Min SDK:** {}\n".format(test_description, data["min"]) - - if "targetsdk" in data: - test_description = "{} **Target SDK:** {}\n".format(test_description, data["targetsdk"]) - - if "minsdk" in data: - test_description = "{} **Min SDK:** {}\n".format(test_description, data["minsdk"]) - - if "maxsdk" in data: - test_description = "{} **Max SDK:** {}\n".format(test_description, data["maxsdk"]) - - test_description = f"{test_description}\n**File Information:**\n" - - if "name" in data: - test_description = "{} **Name:** {}\n".format(test_description, data["name"]) - - if "md5" in data: - test_description = "{} **MD5:** {}\n".format(test_description, data["md5"]) - - if "sha1" in data: - test_description = "{} **SHA-1:** {}\n".format(test_description, data["sha1"]) - - if "sha256" in data: - test_description = "{} **SHA-256:** {}\n".format(test_description, data["sha256"]) - - if "size" in data: - test_description = "{} **Size:** {}\n".format(test_description, data["size"]) - - if "urls" in data: - curl = "" - for url in data["urls"]: - for durl in url["urls"]: - curl = f"{durl}\n" - - if curl: - test_description = f"{test_description}\n**URL's:**\n {curl}\n" - - if "bin_anal" in data: - test_description = "{} \n**Binary Analysis:** {}\n".format(test_description, data["bin_anal"]) - - test.description = html2text(test_description) - - mobsf_findings = [] - # Mobile Permissions - if "permissions" in data: - # for permission, details in data["permissions"].items(): - if isinstance(data["permissions"], list): - for details in data["permissions"]: - mobsf_item = { - "category": "Mobile Permissions", - "title": details.get("name", ""), - "severity": self.getSeverityForPermission(details.get("status")), - "description": "**Permission Type:** " + details.get("name", "") + " (" + details.get("status", "") + ")\n\n**Description:** " + details.get("description", "") + "\n\n**Reason:** " + details.get("reason", ""), - "file_path": None, - } - mobsf_findings.append(mobsf_item) - else: - for permission, details in list(data["permissions"].items()): - mobsf_item = { - "category": "Mobile Permissions", - "title": permission, - "severity": self.getSeverityForPermission(details.get("status", "")), - "description": "**Permission Type:** " + permission + "\n\n**Description:** " + details.get("description", ""), - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # Insecure Connections - if "insecure_connections" in data: - for details in data["insecure_connections"]: - insecure_urls = "" - for url in details.split(","): - insecure_urls = insecure_urls + url + "\n" - - mobsf_item = { - "category": None, - "title": "Insecure Connections", - "severity": "Low", - "description": insecure_urls, - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # Certificate Analysis - if "certificate_analysis" in data: - if data["certificate_analysis"] != {}: - certificate_info = data["certificate_analysis"]["certificate_info"] - for details in data["certificate_analysis"]["certificate_findings"]: - if len(details) == 3: - mobsf_item = { - "category": "Certificate Analysis", - "title": details[2], - "severity": details[0].title(), - "description": details[1] + "\n\n**Certificate Info:** " + certificate_info, - "file_path": None, - } - mobsf_findings.append(mobsf_item) - elif len(details) == 2: - mobsf_item = { - "category": "Certificate Analysis", - "title": details[1], - "severity": details[0].title(), - "description": details[1] + "\n\n**Certificate Info:** " + certificate_info, - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # Manifest Analysis - if "manifest_analysis" in data: - if data["manifest_analysis"] != {} and isinstance(data["manifest_analysis"], dict): - if data["manifest_analysis"]["manifest_findings"]: - for details in data["manifest_analysis"]["manifest_findings"]: - mobsf_item = { - "category": "Manifest Analysis", - "title": details["title"], - "severity": details["severity"].title(), - "description": details["description"] + "\n\n " + details["name"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - else: - for details in data["manifest_analysis"]: - mobsf_item = { - "category": "Manifest Analysis", - "title": details["title"], - "severity": details["stat"].title(), - "description": details["desc"] + "\n\n " + details["name"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # Code Analysis - if "code_analysis" in data: - if data["code_analysis"] != {}: - if data["code_analysis"].get("findings"): - for details in data["code_analysis"]["findings"]: - metadata = data["code_analysis"]["findings"][details] - mobsf_item = { - "category": "Code Analysis", - "title": details, - "severity": metadata["metadata"]["severity"].title(), - "description": metadata["metadata"]["description"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - else: - for details in data["code_analysis"]: - metadata = data["code_analysis"][details] - if metadata.get("metadata"): - mobsf_item = { - "category": "Code Analysis", - "title": details, - "severity": metadata["metadata"]["severity"].title(), - "description": metadata["metadata"]["description"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # Binary Analysis - if "binary_analysis" in data: - if isinstance(data["binary_analysis"], list): - for details in data["binary_analysis"]: - for binary_analysis_type in details: - if binary_analysis_type != "name": - mobsf_item = { - "category": "Binary Analysis", - "title": details[binary_analysis_type]["description"].split(".")[0], - "severity": details[binary_analysis_type]["severity"].title(), - "description": details[binary_analysis_type]["description"], - "file_path": details["name"], - } - mobsf_findings.append(mobsf_item) - elif data["binary_analysis"].get("findings"): - for details in data["binary_analysis"]["findings"].values(): - # "findings":{ - # "Binary makes use of insecure API(s)":{ - # "detailed_desc":"The binary may contain the following insecure API(s) _memcpy\n, _strlen\n", - # "severity":"high", - # "cvss":6, - # "cwe":"CWE-676: Use of Potentially Dangerous Function", - # "owasp-mobile":"M7: Client Code Quality", - # "masvs":"MSTG-CODE-8" - # }, - mobsf_item = { - "category": "Binary Analysis", - "title": details["detailed_desc"], - "severity": details["severity"].title(), - "description": details["detailed_desc"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - else: - for details in data["binary_analysis"].values(): - # "Binary makes use of insecure API(s)":{ - # "detailed_desc":"The binary may contain the following insecure API(s) _vsprintf.", - # "severity":"high", - # "cvss":6, - # "cwe":"CWE-676 - Use of Potentially Dangerous Function", - # "owasp-mobile":"M7: Client Code Quality", - # "masvs":"MSTG-CODE-8" - # } - mobsf_item = { - "category": "Binary Analysis", - "title": details["detailed_desc"], - "severity": details["severity"].title(), - "description": details["detailed_desc"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # specific node for Android reports - if "android_api" in data: - # "android_insecure_random": { - # "files": { - # "u/c/a/b/a/c.java": "9", - # "kotlinx/coroutines/repackaged/net/bytebuddy/utility/RandomString.java": "3", - # ... - # "hu/mycompany/vbnmqweq/gateway/msg/Response.java": "13" - # }, - # "metadata": { - # "id": "android_insecure_random", - # "description": "The App uses an insecure Random Number Generator.", - # "type": "Regex", - # "pattern": "java\\.util\\.Random;", - # "severity": "high", - # "input_case": "exact", - # "cvss": 7.5, - # "cwe": "CWE-330 Use of Insufficiently Random Values", - # "owasp-mobile": "M5: Insufficient Cryptography", - # "masvs": "MSTG-CRYPTO-6" - # } - # }, - for api, details in list(data["android_api"].items()): - mobsf_item = { - "category": "Android API", - "title": details["metadata"]["description"], - "severity": details["metadata"]["severity"].title(), - "description": "**API:** " + api + "\n\n**Description:** " + details["metadata"]["description"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # Manifest - if "manifest" in data: - for details in data["manifest"]: - mobsf_item = { - "category": "Manifest", - "title": details["title"], - "severity": details["stat"], - "description": details["desc"], - "file_path": None, - } - mobsf_findings.append(mobsf_item) - - # MobSF Findings - if "findings" in data: - for title, finding in list(data["findings"].items()): - description = title - file_path = None - - if "path" in finding: - description += "\n\n**Files:**\n" - for path in finding["path"]: - if file_path is None: - file_path = path - description = description + " * " + path + "\n" - - mobsf_item = { - "category": "Findings", - "title": title, - "severity": finding["level"], - "description": description, - "file_path": file_path, - } - - mobsf_findings.append(mobsf_item) - if isinstance(data, list): - for finding in data: - mobsf_item = { - "category": finding["category"], - "title": finding["name"], - "severity": finding["severity"], - "description": finding["description"] + "\n" + "**apk_exploit_dict:** " + str(finding["apk_exploit_dict"]) + "\n" + "**line_number:** " + str(finding["line_number"]), - "file_path": finding["file_object"], - } - mobsf_findings.append(mobsf_item) - for mobsf_finding in mobsf_findings: - title = mobsf_finding["title"] - sev = self.getCriticalityRating(mobsf_finding["severity"]) - description = "" - file_path = None - if mobsf_finding["category"]: - description += "**Category:** " + mobsf_finding["category"] + "\n\n" - description += html2text(mobsf_finding["description"]) - finding = Finding( - title=title, - cwe=919, # Weaknesses in Mobile Applications - test=test, - description=description, - severity=sev, - references=None, - date=find_date, - static_finding=True, - dynamic_finding=False, - nb_occurences=1, - ) - if mobsf_finding["file_path"]: - finding.file_path = mobsf_finding["file_path"] - dupe_key = sev + title + description + mobsf_finding["file_path"] - else: - dupe_key = sev + title + description - if mobsf_finding["category"]: - dupe_key += mobsf_finding["category"] - if dupe_key in dupes: - find = dupes[dupe_key] - if description is not None: - find.description += description - find.nb_occurences += 1 - else: - dupes[dupe_key] = finding - return list(dupes.values()) - - def getSeverityForPermission(self, status): - """ - Convert status for permission detection to severity - - In MobSF there is only 4 know values for permission, - we map them as this: - dangerous => High (Critical?) - normal => Info - signature => Info (it's positive so... Info) - signatureOrSystem => Info (it's positive so... Info) - """ - if status == "dangerous": - return "High" - return "Info" - - # Criticality rating - def getCriticalityRating(self, rating): - criticality = "Info" - if rating.lower() == "good": - criticality = "Info" - elif rating.lower() == "warning": - criticality = "Low" - elif rating.lower() == "vulnerability": - criticality = "Medium" - else: - criticality = rating.lower().capitalize() - return criticality - - def suite_data(self, suites): - suite_info = "" - suite_info += suites["name"] + "\n" - suite_info += "Cipher Strength: " + str(suites["cipherStrength"]) + "\n" - if "ecdhBits" in suites: - suite_info += "ecdhBits: " + str(suites["ecdhBits"]) + "\n" - if "ecdhStrength" in suites: - suite_info += "ecdhStrength: " + str(suites["ecdhStrength"]) - suite_info += "\n\n" - return suite_info + if isinstance(data, list) or data.get("results") is None: + return MobSFapireport().get_findings(data, test) + if len(data.get("results")) == 0: + return [] + return MobSFjsonreport().get_findings(data, test) diff --git a/dojo/tools/mobsfscan/parser.py b/dojo/tools/mobsf/report.py similarity index 84% rename from dojo/tools/mobsfscan/parser.py rename to dojo/tools/mobsf/report.py index 49995720acb..3f076e2f8a5 100644 --- a/dojo/tools/mobsfscan/parser.py +++ b/dojo/tools/mobsf/report.py @@ -1,11 +1,10 @@ import hashlib -import json import re from dojo.models import Finding -class MobsfscanParser: +class MobSFjsonreport: """A class that can be used to parse the mobsfscan (https://github.com/MobSF/mobsfscan) JSON report file.""" @@ -15,19 +14,7 @@ class MobsfscanParser: "INFO": "Low", } - def get_scan_types(self): - return ["Mobsfscan Scan"] - - def get_label_for_scan_types(self, scan_type): - return "Mobsfscan Scan" - - def get_description_for_scan_types(self, scan_type): - return "Import JSON report for mobsfscan report file." - - def get_findings(self, filename, test): - data = json.load(filename) - if len(data.get("results")) == 0: - return [] + def get_findings(self, data, test): dupes = {} for key, item in data.get("results").items(): metadata = item.get("metadata") diff --git a/dojo/tools/mobsfscan/__init__.py b/dojo/tools/mobsfscan/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/unittests/scans/mobsfscan/many_findings.json b/unittests/scans/mobsf/many_findings.json similarity index 100% rename from unittests/scans/mobsfscan/many_findings.json rename to unittests/scans/mobsf/many_findings.json diff --git a/unittests/scans/mobsfscan/many_findings_cwe_lower.json b/unittests/scans/mobsf/many_findings_cwe_lower.json similarity index 100% rename from unittests/scans/mobsfscan/many_findings_cwe_lower.json rename to unittests/scans/mobsf/many_findings_cwe_lower.json diff --git a/unittests/scans/mobsfscan/no_findings.json b/unittests/scans/mobsf/no_findings.json similarity index 100% rename from unittests/scans/mobsfscan/no_findings.json rename to unittests/scans/mobsf/no_findings.json diff --git a/unittests/tools/test_mobsf_parser.py b/unittests/tools/test_mobsf_parser.py index 53ddbb8a3e6..88719e57d88 100644 --- a/unittests/tools/test_mobsf_parser.py +++ b/unittests/tools/test_mobsf_parser.py @@ -136,3 +136,162 @@ def test_parse_damnvulnrablebank(self): findings = parser.get_findings(testfile, test) testfile.close() self.assertEqual(80, len(findings)) + + def test_parse_no_findings(self): + with (get_unit_tests_scans_path("mobsf") / "no_findings.json").open(encoding="utf-8") as testfile: + parser = MobSFParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) + + def test_parse_many_findings(self): + with (get_unit_tests_scans_path("mobsf") / "many_findings.json").open(encoding="utf-8") as testfile: + parser = MobSFParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(8, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("android_certificate_transparency", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("android_kotlin_hardcoded", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.references) + self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) + self.assertEqual(10, finding.line) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("android_kotlin_hardcoded", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.references) + self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures2.kt", finding.file_path) + self.assertEqual(20, finding.line) + + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("android_prevent_screenshot", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=4): + finding = findings[4] + self.assertEqual("android_root_detection", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(919, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("android_safetynet", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(353, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=6): + finding = findings[6] + self.assertEqual("android_ssl_pinning", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=7): + finding = findings[7] + self.assertEqual("android_tapjacking", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) + + def test_parse_many_findings_cwe_lower(self): + with (get_unit_tests_scans_path("mobsf") / "many_findings_cwe_lower.json").open(encoding="utf-8") as testfile: + parser = MobSFParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(7, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("android_certificate_transparency", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("android_kotlin_hardcoded", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.references) + self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) + self.assertEqual(10, finding.line) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("android_prevent_screenshot", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("android_root_detection", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(919, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=4): + finding = findings[4] + self.assertEqual("android_safetynet", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(353, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("android_ssl_pinning", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=6): + finding = findings[6] + self.assertEqual("android_tapjacking", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) diff --git a/unittests/tools/test_mobsfscan_parser.py b/unittests/tools/test_mobsfscan_parser.py deleted file mode 100644 index cbb6245c227..00000000000 --- a/unittests/tools/test_mobsfscan_parser.py +++ /dev/null @@ -1,165 +0,0 @@ -from dojo.models import Test -from dojo.tools.mobsfscan.parser import MobsfscanParser -from unittests.dojo_test_case import DojoTestCase, get_unit_tests_scans_path - - -class TestMobsfscanParser(DojoTestCase): - - def test_parse_no_findings(self): - with (get_unit_tests_scans_path("mobsfscan") / "no_findings.json").open(encoding="utf-8") as testfile: - parser = MobsfscanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) - - def test_parse_many_findings(self): - with (get_unit_tests_scans_path("mobsfscan") / "many_findings.json").open(encoding="utf-8") as testfile: - parser = MobsfscanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(8, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("android_certificate_transparency", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("android_kotlin_hardcoded", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.references) - self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) - self.assertEqual(10, finding.line) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("android_kotlin_hardcoded", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.references) - self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures2.kt", finding.file_path) - self.assertEqual(20, finding.line) - - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("android_prevent_screenshot", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=4): - finding = findings[4] - self.assertEqual("android_root_detection", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(919, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("android_safetynet", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(353, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=6): - finding = findings[6] - self.assertEqual("android_ssl_pinning", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=7): - finding = findings[7] - self.assertEqual("android_tapjacking", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) - - def test_parse_many_findings_cwe_lower(self): - with (get_unit_tests_scans_path("mobsfscan") / "many_findings_cwe_lower.json").open(encoding="utf-8") as testfile: - parser = MobsfscanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(7, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("android_certificate_transparency", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("android_kotlin_hardcoded", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.references) - self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) - self.assertEqual(10, finding.line) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("android_prevent_screenshot", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("android_root_detection", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(919, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=4): - finding = findings[4] - self.assertEqual("android_safetynet", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(353, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("android_ssl_pinning", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=6): - finding = findings[6] - self.assertEqual("android_tapjacking", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) From 9ecc66b2a9c6dbcbe72cba7d1bc1ff7e4f1888b3 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Mon, 26 May 2025 09:48:09 +0200 Subject: [PATCH 02/18] add migration --- dojo/db_migrations/0229_merge_mobsf.py | 55 ++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 dojo/db_migrations/0229_merge_mobsf.py diff --git a/dojo/db_migrations/0229_merge_mobsf.py b/dojo/db_migrations/0229_merge_mobsf.py new file mode 100644 index 00000000000..6d2bb9ca33a --- /dev/null +++ b/dojo/db_migrations/0229_merge_mobsf.py @@ -0,0 +1,55 @@ +from django.db import migrations +import logging + + +logger = logging.getLogger(__name__) + + +PARSER_REFERENCES = ['Mobsfscan Scan'] + + +def update_parser_test(test, parser_test_type) -> None: + if test.test_type.name in PARSER_REFERENCES or test.scan_type in PARSER_REFERENCES: + test.test_type = parser_test_type + test.scan_type = parser_test_type.name + test.save() + + +# Update the found_by field to remove Mobsfscan Scan and add MobSF Scan +def update_parser_finding(finding, newparser_test_type, parser_test_type) -> None: + # Check if nessus is in found by list and remove + if parser_test_type in finding.found_by.all(): + finding.found_by.remove(parser_test_type.id) + # Check if tenable is already in list somehow before adding it + if newparser_test_type not in finding.found_by.all(): + finding.found_by.add(newparser_test_type.id) + finding.save() + + +# Update all finding objects that came from Mobsfscan Scan reports +def forward_merge_parser(apps, schema_editor): + finding_model = apps.get_model('dojo', 'Finding') + test_type_model = apps.get_model('dojo', 'Test_Type') + # Get or create MobSF Scan Test Type and fetch the Mobsfscan Scan test types + newparser_test_type, _ = test_type_model.objects.get_or_create(name="MobSF Scan", defaults={"active": True}) + parser_test_type = test_type_model.objects.filter(name="Mobsfscan Scan").first() + # Get all the findings found by Mobsfscan Scan + findings = finding_model.objects.filter(test__scan_type__in=PARSER_REFERENCES) + logger.warning(f'We identified {findings.count()} Mobsfscan Scan findings to migrate to MobSF Scan findings') + # Iterate over all findings and change + for finding in findings: + # Update the found by field + update_parser_finding(finding, newparser_test_type, parser_test_type) + # Update the test object + update_parser_test(finding.test, newparser_test_type) + + +class Migration(migrations.Migration): + + dependencies = [ + ('dojo', '0228_alter_jira_username_password'), + ] + + operations = [ + migrations.RunPython(forward_merge_parser), + ] From e12dd0d209fce5b41d66026796f5fb75f88f55eb Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Mon, 26 May 2025 13:55:03 +0200 Subject: [PATCH 03/18] udpate --- dojo/settings/settings.dist.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 76a82c39c28..2656baba65c 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1272,7 +1272,6 @@ def saml2_attrib_map_format(din): "Dockle Scan": ["title", "description", "vuln_id_from_tool"], "Dependency Track Finding Packaging Format (FPF) Export": ["component_name", "component_version", "vulnerability_ids"], "Horusec Scan": ["title", "description", "file_path", "line"], - "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 @@ -1333,7 +1332,7 @@ def saml2_attrib_map_format(din): "HCLAppScan XML": ["title", "description"], "HCL AppScan on Cloud SAST XML": ["title", "file_path", "line", "severity"], "KICS Scan": ["file_path", "line", "severity", "description", "title"], - "MobSF Scan": ["title", "description", "severity"], + "MobSF Scan": ["title", "severity", "cwe", "file_path", "description"], "MobSF Scorecard Scan": ["title", "description", "severity"], "OSV Scan": ["title", "description", "severity"], "Snyk Code Scan": ["vuln_id_from_tool", "file_path"], @@ -1392,7 +1391,6 @@ def saml2_attrib_map_format(din): "Cloudsploit Scan": True, "SonarQube Scan": False, "Dependency Check Scan": True, - "Mobsfscan Scan": False, "Tenable Scan": True, "Nexpose Scan": True, "NPM Audit Scan": True, @@ -1502,7 +1500,6 @@ def saml2_attrib_map_format(din): "Crunch42 Scan": DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL, "Dependency Track Finding Packaging Format (FPF) Export": DEDUPE_ALGO_HASH_CODE, "Horusec Scan": DEDUPE_ALGO_HASH_CODE, - "Mobsfscan Scan": DEDUPE_ALGO_HASH_CODE, "SonarQube Scan detailed": DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL, "SonarQube Scan": DEDUPE_ALGO_HASH_CODE, "SonarQube API Import": DEDUPE_ALGO_HASH_CODE, From 2d99a6cb5db736e62a8891f392d400a4594e9a26 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Mon, 26 May 2025 23:08:02 +0200 Subject: [PATCH 04/18] Update 0229_merge_mobsf.py --- dojo/db_migrations/0229_merge_mobsf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dojo/db_migrations/0229_merge_mobsf.py b/dojo/db_migrations/0229_merge_mobsf.py index 6d2bb9ca33a..3ae29748c66 100644 --- a/dojo/db_migrations/0229_merge_mobsf.py +++ b/dojo/db_migrations/0229_merge_mobsf.py @@ -17,10 +17,10 @@ def update_parser_test(test, parser_test_type) -> None: # Update the found_by field to remove Mobsfscan Scan and add MobSF Scan def update_parser_finding(finding, newparser_test_type, parser_test_type) -> None: - # Check if nessus is in found by list and remove + # Check if old parser is in found by list and remove if parser_test_type in finding.found_by.all(): finding.found_by.remove(parser_test_type.id) - # Check if tenable is already in list somehow before adding it + # Check if new parser is already in list somehow before adding it if newparser_test_type not in finding.found_by.all(): finding.found_by.add(newparser_test_type.id) finding.save() From 6669f30cb09e14b601d71a2b4e01fd3f70100705 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Tue, 27 May 2025 10:20:37 +0200 Subject: [PATCH 05/18] udpate --- docs/content/en/open_source/upgrading/2.48.md | 2 +- docs/content/en/open_source/upgrading/2.49.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/content/en/open_source/upgrading/2.48.md b/docs/content/en/open_source/upgrading/2.48.md index 8d992f9d90a..56031020b8e 100644 --- a/docs/content/en/open_source/upgrading/2.48.md +++ b/docs/content/en/open_source/upgrading/2.48.md @@ -8,4 +8,4 @@ description: Better pushing to JIRA for Finding Groups ## Finding Group JIRA Issue template changes As part of [PR 12475](https://github.com/DefectDojo/django-DefectDojo/pull/12475) the [jira-finding-group-description.tpl](https://github.com/DefectDojo/django-DefectDojo/blob/master/dojo/templates/issue-trackers/jira_full/jira-finding-group-description.tpl) was updated. If you're using a custom set of JIRA template files, please review the PR for any changes you need to take into account. -There are no special instructions for upgrading to 2.48.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.48.0) for the contents of the release. \ No newline at end of file +There are no special instructions for upgrading to 2.48.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.48.0) for the contents of the release. diff --git a/docs/content/en/open_source/upgrading/2.49.md b/docs/content/en/open_source/upgrading/2.49.md index 188201bbb88..114035c06d8 100644 --- a/docs/content/en/open_source/upgrading/2.49.md +++ b/docs/content/en/open_source/upgrading/2.49.md @@ -5,3 +5,7 @@ weight: -20250707 description: No special instructions. --- There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. + +### Merging Mobsfscan Scan and MobSF Scan + +The two scan types Mobsfscan Scan and MobSF Scan were merged in this release. We recommend to recalculate the hashcodes if you use these parsers as the deduplication settings have been changed. From 24de7ed18e1298b0ab7783c5f9f7a1f4c3da114e Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Fri, 30 May 2025 08:52:41 +0200 Subject: [PATCH 06/18] Update settings.dist.py --- dojo/settings/settings.dist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 2656baba65c..d894a66d68e 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1332,7 +1332,7 @@ def saml2_attrib_map_format(din): "HCLAppScan XML": ["title", "description"], "HCL AppScan on Cloud SAST XML": ["title", "file_path", "line", "severity"], "KICS Scan": ["file_path", "line", "severity", "description", "title"], - "MobSF Scan": ["title", "severity", "cwe", "file_path", "description"], + "MobSF Scan": ["title", "description", "severity", "file_path"], "MobSF Scorecard Scan": ["title", "description", "severity"], "OSV Scan": ["title", "description", "severity"], "Snyk Code Scan": ["vuln_id_from_tool", "file_path"], From f011f22a72006164e90519c4fa34f1ce96d3b583 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Fri, 30 May 2025 09:09:00 +0200 Subject: [PATCH 07/18] update --- dojo/db_migrations/{0229_merge_mobsf.py => 0230_merge_mobsf.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename dojo/db_migrations/{0229_merge_mobsf.py => 0230_merge_mobsf.py} (97%) diff --git a/dojo/db_migrations/0229_merge_mobsf.py b/dojo/db_migrations/0230_merge_mobsf.py similarity index 97% rename from dojo/db_migrations/0229_merge_mobsf.py rename to dojo/db_migrations/0230_merge_mobsf.py index 3ae29748c66..ed0135a3239 100644 --- a/dojo/db_migrations/0229_merge_mobsf.py +++ b/dojo/db_migrations/0230_merge_mobsf.py @@ -47,7 +47,7 @@ def forward_merge_parser(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('dojo', '0228_alter_jira_username_password'), + ('dojo', '0229_alter_finding_unique_id_from_tool'), ] operations = [ From 3516e4ec3226b55968861f755e8bb61741a7ab87 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Fri, 20 Jun 2025 13:57:48 +0200 Subject: [PATCH 08/18] update --- dojo/db_migrations/0230_merge_mobsf.py | 55 -------------------------- dojo/settings/settings.dist.py | 3 ++ dojo/tools/mobsf/parser.py | 2 +- 3 files changed, 4 insertions(+), 56 deletions(-) delete mode 100644 dojo/db_migrations/0230_merge_mobsf.py diff --git a/dojo/db_migrations/0230_merge_mobsf.py b/dojo/db_migrations/0230_merge_mobsf.py deleted file mode 100644 index ed0135a3239..00000000000 --- a/dojo/db_migrations/0230_merge_mobsf.py +++ /dev/null @@ -1,55 +0,0 @@ -from django.db import migrations -import logging - - -logger = logging.getLogger(__name__) - - -PARSER_REFERENCES = ['Mobsfscan Scan'] - - -def update_parser_test(test, parser_test_type) -> None: - if test.test_type.name in PARSER_REFERENCES or test.scan_type in PARSER_REFERENCES: - test.test_type = parser_test_type - test.scan_type = parser_test_type.name - test.save() - - -# Update the found_by field to remove Mobsfscan Scan and add MobSF Scan -def update_parser_finding(finding, newparser_test_type, parser_test_type) -> None: - # Check if old parser is in found by list and remove - if parser_test_type in finding.found_by.all(): - finding.found_by.remove(parser_test_type.id) - # Check if new parser is already in list somehow before adding it - if newparser_test_type not in finding.found_by.all(): - finding.found_by.add(newparser_test_type.id) - finding.save() - - -# Update all finding objects that came from Mobsfscan Scan reports -def forward_merge_parser(apps, schema_editor): - finding_model = apps.get_model('dojo', 'Finding') - test_type_model = apps.get_model('dojo', 'Test_Type') - # Get or create MobSF Scan Test Type and fetch the Mobsfscan Scan test types - newparser_test_type, _ = test_type_model.objects.get_or_create(name="MobSF Scan", defaults={"active": True}) - parser_test_type = test_type_model.objects.filter(name="Mobsfscan Scan").first() - # Get all the findings found by Mobsfscan Scan - findings = finding_model.objects.filter(test__scan_type__in=PARSER_REFERENCES) - logger.warning(f'We identified {findings.count()} Mobsfscan Scan findings to migrate to MobSF Scan findings') - # Iterate over all findings and change - for finding in findings: - # Update the found by field - update_parser_finding(finding, newparser_test_type, parser_test_type) - # Update the test object - update_parser_test(finding.test, newparser_test_type) - - -class Migration(migrations.Migration): - - dependencies = [ - ('dojo', '0229_alter_finding_unique_id_from_tool'), - ] - - operations = [ - migrations.RunPython(forward_merge_parser), - ] diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index d894a66d68e..442c5af6cd2 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1272,6 +1272,7 @@ def saml2_attrib_map_format(din): "Dockle Scan": ["title", "description", "vuln_id_from_tool"], "Dependency Track Finding Packaging Format (FPF) Export": ["component_name", "component_version", "vulnerability_ids"], "Horusec Scan": ["title", "description", "file_path", "line"], + "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 @@ -1391,6 +1392,7 @@ def saml2_attrib_map_format(din): "Cloudsploit Scan": True, "SonarQube Scan": False, "Dependency Check Scan": True, + "Mobsfscan Scan": False, "Tenable Scan": True, "Nexpose Scan": True, "NPM Audit Scan": True, @@ -1500,6 +1502,7 @@ def saml2_attrib_map_format(din): "Crunch42 Scan": DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL, "Dependency Track Finding Packaging Format (FPF) Export": DEDUPE_ALGO_HASH_CODE, "Horusec Scan": DEDUPE_ALGO_HASH_CODE, + "Mobsfscan Scan": DEDUPE_ALGO_HASH_CODE, "SonarQube Scan detailed": DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL, "SonarQube Scan": DEDUPE_ALGO_HASH_CODE, "SonarQube API Import": DEDUPE_ALGO_HASH_CODE, diff --git a/dojo/tools/mobsf/parser.py b/dojo/tools/mobsf/parser.py index d9e8b419aa0..ff5a7122655 100644 --- a/dojo/tools/mobsf/parser.py +++ b/dojo/tools/mobsf/parser.py @@ -8,7 +8,7 @@ class MobSFParser: def get_scan_types(self): - return ["MobSF Scan"] + return ["MobSF Scan", "Mobsfscan Scan"] def get_label_for_scan_types(self, scan_type): return "MobSF Scan" From 5646b0c539579a38c1ad1e44718b11ce60810a48 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Thu, 3 Jul 2025 08:27:26 +0200 Subject: [PATCH 09/18] update docs --- docs/content/en/connecting_your_tools/parsers/file/mobsf.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/content/en/connecting_your_tools/parsers/file/mobsf.md b/docs/content/en/connecting_your_tools/parsers/file/mobsf.md index 9d827b20df5..caac14fbf14 100644 --- a/docs/content/en/connecting_your_tools/parsers/file/mobsf.md +++ b/docs/content/en/connecting_your_tools/parsers/file/mobsf.md @@ -2,6 +2,8 @@ title: "MobSF Scanner" toc_hide: true --- +"Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. + Export a JSON file using the API, api/v1/report\_json and import it to Defectdojo or import a JSON report from ### Sample Scan Data From 5e76ed324881fb7fd8ff883d6bc0f8e8bc8c54a8 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Thu, 3 Jul 2025 08:29:49 +0200 Subject: [PATCH 10/18] Update 2.48.md --- docs/content/en/open_source/upgrading/2.48.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/open_source/upgrading/2.48.md b/docs/content/en/open_source/upgrading/2.48.md index 56031020b8e..215014f6cb8 100644 --- a/docs/content/en/open_source/upgrading/2.48.md +++ b/docs/content/en/open_source/upgrading/2.48.md @@ -2,7 +2,7 @@ title: 'Upgrading to DefectDojo Version 2.48.x' toc_hide: true weight: -20250602 -description: Better pushing to JIRA for Finding Groups +description: MobSF parser merged, Better pushing to JIRA for Finding Groups --- ## Finding Group JIRA Issue template changes From d5e62373294693be663462a164a9f8f8d1cd0cd8 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Wed, 16 Jul 2025 09:50:15 +0200 Subject: [PATCH 11/18] update upgrade notes --- docs/content/en/open_source/upgrading/2.49.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/en/open_source/upgrading/2.49.md b/docs/content/en/open_source/upgrading/2.49.md index 114035c06d8..415f70a5873 100644 --- a/docs/content/en/open_source/upgrading/2.49.md +++ b/docs/content/en/open_source/upgrading/2.49.md @@ -4,8 +4,8 @@ toc_hide: true weight: -20250707 description: No special instructions. --- -There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. +### Merge of MobSF parsers -### Merging Mobsfscan Scan and MobSF Scan +Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. -The two scan types Mobsfscan Scan and MobSF Scan were merged in this release. We recommend to recalculate the hashcodes if you use these parsers as the deduplication settings have been changed. +There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. \ No newline at end of file From 1a9e27cb876d73bb28a708fb5ba847ba29ebb3cb Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:51:16 +0200 Subject: [PATCH 12/18] Update 2.48.md --- docs/content/en/open_source/upgrading/2.48.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/open_source/upgrading/2.48.md b/docs/content/en/open_source/upgrading/2.48.md index 215014f6cb8..56031020b8e 100644 --- a/docs/content/en/open_source/upgrading/2.48.md +++ b/docs/content/en/open_source/upgrading/2.48.md @@ -2,7 +2,7 @@ title: 'Upgrading to DefectDojo Version 2.48.x' toc_hide: true weight: -20250602 -description: MobSF parser merged, Better pushing to JIRA for Finding Groups +description: Better pushing to JIRA for Finding Groups --- ## Finding Group JIRA Issue template changes From 673702c40ef06bb32ff585a8e721365dd7d86455 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:51:55 +0200 Subject: [PATCH 13/18] Update 2.48.md From c6b8adda58e11e6824a68390278edfa1b5000aff Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Wed, 16 Jul 2025 09:53:45 +0200 Subject: [PATCH 14/18] fix --- docs/content/en/open_source/upgrading/2.48.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/open_source/upgrading/2.48.md b/docs/content/en/open_source/upgrading/2.48.md index 56031020b8e..8d992f9d90a 100644 --- a/docs/content/en/open_source/upgrading/2.48.md +++ b/docs/content/en/open_source/upgrading/2.48.md @@ -8,4 +8,4 @@ description: Better pushing to JIRA for Finding Groups ## Finding Group JIRA Issue template changes As part of [PR 12475](https://github.com/DefectDojo/django-DefectDojo/pull/12475) the [jira-finding-group-description.tpl](https://github.com/DefectDojo/django-DefectDojo/blob/master/dojo/templates/issue-trackers/jira_full/jira-finding-group-description.tpl) was updated. If you're using a custom set of JIRA template files, please review the PR for any changes you need to take into account. -There are no special instructions for upgrading to 2.48.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.48.0) for the contents of the release. +There are no special instructions for upgrading to 2.48.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.48.0) for the contents of the release. \ No newline at end of file From ee6f11c8eb0dcd8d625c6dc39b6cfaa5be65a0fb Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Fri, 29 Aug 2025 14:18:35 +0200 Subject: [PATCH 15/18] update --- docs/content/en/open_source/upgrading/2.49.md | 4 ---- docs/content/en/open_source/upgrading/2.50.md | 8 +++++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/content/en/open_source/upgrading/2.49.md b/docs/content/en/open_source/upgrading/2.49.md index 415f70a5873..409e0f80df7 100644 --- a/docs/content/en/open_source/upgrading/2.49.md +++ b/docs/content/en/open_source/upgrading/2.49.md @@ -4,8 +4,4 @@ toc_hide: true weight: -20250707 description: No special instructions. --- -### Merge of MobSF parsers - -Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. - There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. \ No newline at end of file diff --git a/docs/content/en/open_source/upgrading/2.50.md b/docs/content/en/open_source/upgrading/2.50.md index 289f833a03f..21ac7c1affa 100644 --- a/docs/content/en/open_source/upgrading/2.50.md +++ b/docs/content/en/open_source/upgrading/2.50.md @@ -2,10 +2,16 @@ title: 'Upgrading to DefectDojo Version 2.50.x' toc_hide: true weight: -20250804 -description: Dropped support for time_zone in System settings. +description: Dropped support for time_zone in System settings and merged MobSF parsers --- To simplify the management of the DefectDojo application, it is not necessary to set the time zone in two places (environmental variables and system settings). From now on, environmental variable is supported. Please check that the environmental variable `DD_TIME_ZONE` is set based on your satisfaction. Any [TZ identifier](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is a valid value. Default value is `UTC`. There are other instructions for upgrading to 2.50.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.50.0) for the contents of the release. + +### Merge of MobSF parsers + +Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. + +There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. \ No newline at end of file From 3925a9810d17a409ac8df2567c4800573aacdddc Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Mon, 15 Sep 2025 22:28:33 +0200 Subject: [PATCH 16/18] update --- docs/content/en/open_source/upgrading/2.50.md | 10 ++-------- docs/content/en/open_source/upgrading/2.51.md | 7 +++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/content/en/open_source/upgrading/2.50.md b/docs/content/en/open_source/upgrading/2.50.md index 21ac7c1affa..d1e82a24280 100644 --- a/docs/content/en/open_source/upgrading/2.50.md +++ b/docs/content/en/open_source/upgrading/2.50.md @@ -2,16 +2,10 @@ title: 'Upgrading to DefectDojo Version 2.50.x' toc_hide: true weight: -20250804 -description: Dropped support for time_zone in System settings and merged MobSF parsers +description: Dropped support for time_zone in System settings. --- To simplify the management of the DefectDojo application, it is not necessary to set the time zone in two places (environmental variables and system settings). From now on, environmental variable is supported. Please check that the environmental variable `DD_TIME_ZONE` is set based on your satisfaction. Any [TZ identifier](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is a valid value. Default value is `UTC`. -There are other instructions for upgrading to 2.50.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.50.0) for the contents of the release. - -### Merge of MobSF parsers - -Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. - -There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. \ No newline at end of file +There are other instructions for upgrading to 2.50.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.50.0) for the contents of the release. \ No newline at end of file diff --git a/docs/content/en/open_source/upgrading/2.51.md b/docs/content/en/open_source/upgrading/2.51.md index fd9cab80d58..120df3b2712 100644 --- a/docs/content/en/open_source/upgrading/2.51.md +++ b/docs/content/en/open_source/upgrading/2.51.md @@ -11,6 +11,13 @@ This release introduces several important changes to the Helm chart configuratio ### Breaking changes +#### Merge of MobSF parsers + +Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. + +There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. + + #### Volume Management Improvements - **Streamlined volume configuration**: The existing volume logic has been removed and replaced with more flexible `extraVolumes` and `extraVolumeMounts` options that provide deployment-agnostic volume management. From 822bf481b01e49cc81aa49a437f9ad1b32a5d44c Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Tue, 16 Sep 2025 07:48:38 +0200 Subject: [PATCH 17/18] update --- docs/content/en/open_source/upgrading/2.49.md | 2 +- docs/content/en/open_source/upgrading/2.50.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/en/open_source/upgrading/2.49.md b/docs/content/en/open_source/upgrading/2.49.md index 409e0f80df7..188201bbb88 100644 --- a/docs/content/en/open_source/upgrading/2.49.md +++ b/docs/content/en/open_source/upgrading/2.49.md @@ -4,4 +4,4 @@ toc_hide: true weight: -20250707 description: No special instructions. --- -There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. \ No newline at end of file +There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. diff --git a/docs/content/en/open_source/upgrading/2.50.md b/docs/content/en/open_source/upgrading/2.50.md index d1e82a24280..289f833a03f 100644 --- a/docs/content/en/open_source/upgrading/2.50.md +++ b/docs/content/en/open_source/upgrading/2.50.md @@ -8,4 +8,4 @@ description: Dropped support for time_zone in System settings. To simplify the management of the DefectDojo application, it is not necessary to set the time zone in two places (environmental variables and system settings). From now on, environmental variable is supported. Please check that the environmental variable `DD_TIME_ZONE` is set based on your satisfaction. Any [TZ identifier](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is a valid value. Default value is `UTC`. -There are other instructions for upgrading to 2.50.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.50.0) for the contents of the release. \ No newline at end of file +There are other instructions for upgrading to 2.50.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.50.0) for the contents of the release. From 591d3f0f5a1dc0341441f8b19385cc51836108e2 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Thu, 16 Oct 2025 07:38:12 +0200 Subject: [PATCH 18/18] update docs --- docs/content/en/open_source/upgrading/2.51.md | 7 ------- docs/content/en/open_source/upgrading/2.52.md | 4 ++++ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/content/en/open_source/upgrading/2.51.md b/docs/content/en/open_source/upgrading/2.51.md index ef769d15ac8..e3cf71186cc 100644 --- a/docs/content/en/open_source/upgrading/2.51.md +++ b/docs/content/en/open_source/upgrading/2.51.md @@ -23,13 +23,6 @@ This release introduces several important changes to the Helm chart configuratio ### Breaking changes -#### Merge of MobSF parsers - -Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. - -There are no special instructions for upgrading to 2.49.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.49.0) for the contents of the release. - - #### Volume Management Improvements - **Streamlined volume configuration**: The existing volume logic has been removed and replaced with more flexible `extraVolumes` and `extraVolumeMounts` options that provide deployment-agnostic volume management. diff --git a/docs/content/en/open_source/upgrading/2.52.md b/docs/content/en/open_source/upgrading/2.52.md index b15986e5228..1619ee0fa81 100644 --- a/docs/content/en/open_source/upgrading/2.52.md +++ b/docs/content/en/open_source/upgrading/2.52.md @@ -11,6 +11,10 @@ This release introduces more important changes to the Helm chart configuration: ### Breaking changes +#### Merge of MobSF parsers + +Mobsfscan Scan" has been merged into the "MobSF Scan" parser. The "Mobsfscan Scan" scan_type has been retained to keep deduplication working for existing Tests, but users are encouraged to move to the "MobSF Scan" scan_type. + #### Security context This Helm chart extends security context capabilities to all deployed pods and containers.