From 458e496a7a24eb70a90e374a0ea41c4a63dadb04 Mon Sep 17 00:00:00 2001 From: Jino Tesauro Date: Wed, 17 Dec 2025 13:18:26 -0600 Subject: [PATCH 1/4] Sonarqube parse creationDate --- dojo/tools/sonarqube/sonarqube_restapi_json.py | 10 ++++++++++ unittests/tools/test_sonarqube_parser.py | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py index f56f362209c..341632b8dac 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_json.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -1,5 +1,7 @@ import re +import dateutil.parser + from dojo.models import Finding @@ -23,6 +25,7 @@ def get_json_items(self, json_content, test, mode): scope = issue.get("scope") quickFixAvailable = str(issue.get("quickFixAvailable")) codeVariants = str(issue.get("codeVariants")) + date = str(dateutil.parser.parse(issue.get("creationDate")).date()) description = "" description += "**key:** " + key + "\n" description += "**rule:** " + rule + "\n" @@ -50,6 +53,7 @@ def get_json_items(self, json_content, test, mode): dynamic_finding=False, tags=["bug"], line=line, + date=date, ) elif issue.get("type") == "VULNERABILITY": key = issue.get("key") @@ -61,6 +65,7 @@ def get_json_items(self, json_content, test, mode): message = issue.get("message") line = issue.get("line") cwe = None + date = str(dateutil.parser.parse(issue.get("creationDate")).date()) if "Category: CWE-" in message: cwe_pattern = r"Category: CWE-\d{1,5}" cwes = re.findall(cwe_pattern, message) @@ -119,6 +124,7 @@ def get_json_items(self, json_content, test, mode): file_path=component, tags=["vulnerability"], line=line, + date=date, ) vulnids = [] if "Reference: CVE" in message: @@ -154,6 +160,7 @@ def get_json_items(self, json_content, test, mode): scope = issue.get("scope") quickFixAvailable = str(issue.get("quickFixAvailable")) codeVariants = issue.get("codeVariants", []) + date = str(dateutil.parser.parse(issue.get("creationDate")).date()) description = "" description += "**rule:** " + rule + "\n" description += "**component:** " + component + "\n" @@ -185,6 +192,7 @@ def get_json_items(self, json_content, test, mode): file_path=component, tags=["code_smell"], line=line, + date=date, ) items.append(item) if json_content.get("hotspots"): @@ -200,6 +208,7 @@ def get_json_items(self, json_content, test, mode): flows = hotspot.get("flows", []) ruleKey = hotspot.get("ruleKey") messageFormattings = hotspot.get("messageFormattings", []) + date = str(dateutil.parser.parse(hotspot.get("creationDate")).date()) description = "" description += "**key:** " + key + "\n" description += "**component:** " + component + "\n" @@ -229,6 +238,7 @@ def get_json_items(self, json_content, test, mode): file_path=component, tags=["hotspot"], line=line, + date=date, ) items.append(item) return items diff --git a/unittests/tools/test_sonarqube_parser.py b/unittests/tools/test_sonarqube_parser.py index c03a6348cab..abe7fda0120 100644 --- a/unittests/tools/test_sonarqube_parser.py +++ b/unittests/tools/test_sonarqube_parser.py @@ -579,20 +579,25 @@ def test_parse_json_file_from_api_with_multiple_findings_json(self): self.assertEqual("6.4", item.cvssv3_score) self.assertEqual("package", item.component_name) self.assertEqual("1.1.2", item.component_version) + self.assertEqual("2023-10-16", item.date) item = findings[1] self.assertEqual("Web:TableWithoutCaptionCheck_asdfwfewfwefewf", item.title) self.assertEqual("Low", item.severity) self.assertEqual(0, item.cwe) self.assertIsNone(item.cvssv3_score) + self.assertEqual("2023-07-25", item.date) item = findings[2] self.assertEqual("typescript:S1533_fjoiewfjoweifjoihugu-", item.title) self.assertEqual("Low", item.severity) + self.assertEqual("2024-01-29", item.date) item = findings[3] self.assertEqual("GHSA-frr2-c345-p7c2", item.unsaved_vulnerability_ids[0]) + self.assertEqual("2023-10-16", item.date) item = findings[4] self.assertEqual("CVE-2023-52428", item.unsaved_vulnerability_ids[0]) self.assertEqual("nimbus-jose-jwt-9.24.4.jar", item.component_name) self.assertIsNone(item.component_version) + self.assertEqual("2023-10-16", item.date) my_file_handle.close() def test_parse_json_file_from_api_with_multiple_findings_hotspots_json(self): @@ -606,12 +611,15 @@ def test_parse_json_file_from_api_with_multiple_findings_hotspots_json(self): self.assertEqual(str, type(item.description)) self.assertEqual("typescript:7777_fwafewef", item.title) self.assertEqual("High", item.severity) + self.assertEqual("2024-02-13", item.date) item = findings[1] self.assertEqual("Web:1222_cyxcvyxcvyxv", item.title) self.assertEqual("Low", item.severity) + self.assertEqual("2023-07-27", item.date) item = findings[2] self.assertEqual("Web:9876_werrwerwerwer", item.title) self.assertEqual("Low", item.severity) + self.assertEqual("2023-07-27", item.date) my_file_handle.close() def test_parse_json_file_from_api_with_empty_json(self): From f43c5df9b6b8b305bf74c9390a88197cc8581642 Mon Sep 17 00:00:00 2001 From: Jino Tesauro Date: Wed, 17 Dec 2025 16:58:30 -0600 Subject: [PATCH 2/4] added better handling of date conversions --- .../tools/sonarqube/sonarqube_restapi_json.py | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py index 341632b8dac..a4e6be03dcd 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_json.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -1,4 +1,5 @@ import re +from datetime import datetime import dateutil.parser @@ -25,7 +26,10 @@ def get_json_items(self, json_content, test, mode): scope = issue.get("scope") quickFixAvailable = str(issue.get("quickFixAvailable")) codeVariants = str(issue.get("codeVariants")) - date = str(dateutil.parser.parse(issue.get("creationDate")).date()) + try: + date = str(dateutil.parser.parse(issue.get("creationDate")).date()) + except (ValueError, TypeError, dateutil.parser.ParserError): + date = datetime.now() description = "" description += "**key:** " + key + "\n" description += "**rule:** " + rule + "\n" @@ -65,7 +69,10 @@ def get_json_items(self, json_content, test, mode): message = issue.get("message") line = issue.get("line") cwe = None - date = str(dateutil.parser.parse(issue.get("creationDate")).date()) + try: + date = str(dateutil.parser.parse(issue.get("creationDate")).date()) + except (ValueError, TypeError, dateutil.parser.ParserError): + date = datetime.now() if "Category: CWE-" in message: cwe_pattern = r"Category: CWE-\d{1,5}" cwes = re.findall(cwe_pattern, message) @@ -160,7 +167,10 @@ def get_json_items(self, json_content, test, mode): scope = issue.get("scope") quickFixAvailable = str(issue.get("quickFixAvailable")) codeVariants = issue.get("codeVariants", []) - date = str(dateutil.parser.parse(issue.get("creationDate")).date()) + try: + date = str(dateutil.parser.parse(issue.get("creationDate")).date()) + except (ValueError, TypeError, dateutil.parser.ParserError): + date = datetime.now() description = "" description += "**rule:** " + rule + "\n" description += "**component:** " + component + "\n" @@ -208,7 +218,10 @@ def get_json_items(self, json_content, test, mode): flows = hotspot.get("flows", []) ruleKey = hotspot.get("ruleKey") messageFormattings = hotspot.get("messageFormattings", []) - date = str(dateutil.parser.parse(hotspot.get("creationDate")).date()) + try: + date = str(dateutil.parser.parse(hotspot.get("creationDate")).date()) + except (ValueError, TypeError, dateutil.parser.ParserError): + date = datetime.now() description = "" description += "**key:** " + key + "\n" description += "**component:** " + component + "\n" From 21f9f17421001a7c38b0c6812e677b0888f8ddec Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:34:54 -0700 Subject: [PATCH 3/4] Apply suggestions from code review --- dojo/tools/sonarqube/sonarqube_restapi_json.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py index a4e6be03dcd..fb37d0cfd5c 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_json.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -2,6 +2,7 @@ from datetime import datetime import dateutil.parser +from django.utils import timezone from dojo.models import Finding @@ -29,7 +30,7 @@ def get_json_items(self, json_content, test, mode): try: date = str(dateutil.parser.parse(issue.get("creationDate")).date()) except (ValueError, TypeError, dateutil.parser.ParserError): - date = datetime.now() + date = timezone.now() description = "" description += "**key:** " + key + "\n" description += "**rule:** " + rule + "\n" @@ -72,7 +73,7 @@ def get_json_items(self, json_content, test, mode): try: date = str(dateutil.parser.parse(issue.get("creationDate")).date()) except (ValueError, TypeError, dateutil.parser.ParserError): - date = datetime.now() + date = timezone.now() if "Category: CWE-" in message: cwe_pattern = r"Category: CWE-\d{1,5}" cwes = re.findall(cwe_pattern, message) @@ -170,7 +171,7 @@ def get_json_items(self, json_content, test, mode): try: date = str(dateutil.parser.parse(issue.get("creationDate")).date()) except (ValueError, TypeError, dateutil.parser.ParserError): - date = datetime.now() + date = timezone.now() description = "" description += "**rule:** " + rule + "\n" description += "**component:** " + component + "\n" @@ -221,7 +222,7 @@ def get_json_items(self, json_content, test, mode): try: date = str(dateutil.parser.parse(hotspot.get("creationDate")).date()) except (ValueError, TypeError, dateutil.parser.ParserError): - date = datetime.now() + date = timezone.now() description = "" description += "**key:** " + key + "\n" description += "**component:** " + component + "\n" From c62c4257868d44e82c5bb285277c6341e63b143d Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:37:07 -0700 Subject: [PATCH 4/4] Update dojo/tools/sonarqube/sonarqube_restapi_json.py --- dojo/tools/sonarqube/sonarqube_restapi_json.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py index fb37d0cfd5c..9feb7a14397 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_json.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -1,5 +1,4 @@ import re -from datetime import datetime import dateutil.parser from django.utils import timezone