Skip to content

Commit 68e2313

Browse files
Fix Qualys parser to prevent merging findings on different ports
1 parent 1c086fb commit 68e2313

3 files changed

Lines changed: 62 additions & 3 deletions

File tree

dojo/tools/qualys/parser.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def get_dedupe_fields(self) -> list[str]:
7878
return [
7979
"title",
8080
"severity",
81+
"endpoints",
8182
]
8283

8384
def get_scan_types(self):
@@ -353,13 +354,18 @@ def parse_finding(host, tree):
353354
if temp.get("CVSS_value") is not None:
354355
finding.cvssv3_score = temp.get("CVSS_value")
355356
finding.verified = True
357+
endpoint_port = None
358+
if port and str(port).isdigit():
359+
endpoint_port = int(port)
356360
# manage endpoint/location
357361
if settings.V3_FEATURE_LOCATIONS:
358-
location = URL(host=issue_row["fqdn"]) if issue_row["fqdn"] else URL(host=issue_row["ip_address"])
362+
host_val = issue_row["fqdn"] if issue_row["fqdn"] else issue_row["ip_address"]
363+
location = URL(host = host_val,port = endpoint_port)
359364
finding.unsaved_locations = [location]
360365
else:
361366
# TODO: Delete this after the move to Locations
362-
location = Endpoint(host=issue_row["fqdn"]) if issue_row["fqdn"] else Endpoint(host=issue_row["ip_address"])
367+
host_val = issue_row["fqdn"] if issue_row["fqdn"] else issue_row["ip_address"]
368+
location = Endpoint(host=host_val,port = endpoint_port)
363369
finding.unsaved_endpoints = [location]
364370
finding.unsaved_vulnerability_ids = temp.get("cve_list", [])
365371
ret_rows.append(finding)
@@ -369,7 +375,7 @@ def parse_finding(host, tree):
369375
def qualys_parser(qualys_xml_file):
370376
parser = ElementTree.XMLParser()
371377
tree = ElementTree.parse(qualys_xml_file, parser)
372-
host_list = tree.find("HOST_LIST")
378+
host_list = tree.find(".//HOST_LIST")
373379
finding_list = []
374380
if host_list is not None:
375381
for host in host_list:
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<QUALYS_REPORT>
3+
<GLOSSARY>
4+
<VULN_DETAILS_LIST>
5+
<VULN_DETAILS id="90001">
6+
<TITLE>SSL Certificate Expired</TITLE>
7+
<SEVERITY>3</SEVERITY>
8+
<THREAT>Threat text</THREAT>
9+
<IMPACT>Impact text</IMPACT>
10+
<SOLUTION>Solution text</SOLUTION>
11+
</VULN_DETAILS>
12+
</VULN_DETAILS_LIST>
13+
</GLOSSARY>
14+
<RESULTS>
15+
<HOST_LIST>
16+
<HOST>
17+
<IP>192.168.1.100</IP>
18+
<VULN_INFO_LIST>
19+
<VULN_INFO>
20+
<QID id="90001"/>
21+
<PORT>80</PORT>
22+
<FIRST_FOUND>2026-02-08T10:00:00Z</FIRST_FOUND>
23+
<LAST_FOUND>2026-02-08T10:00:00Z</LAST_FOUND>
24+
<TYPE>Confirmed</TYPE>
25+
</VULN_INFO>
26+
<VULN_INFO>
27+
<QID id="90001"/>
28+
<PORT>443</PORT>
29+
<FIRST_FOUND>2026-02-08T10:00:00Z</FIRST_FOUND>
30+
<LAST_FOUND>2026-02-08T10:00:00Z</LAST_FOUND>
31+
<TYPE>Confirmed</TYPE>
32+
</VULN_INFO>
33+
</VULN_INFO_LIST>
34+
</HOST>
35+
</HOST_LIST>
36+
</RESULTS>
37+
</QUALYS_REPORT>

unittests/tools/test_qualys_parser.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@ def test_parse_file_with_no_vuln_has_no_findings_first_seen(self):
1616
def test_parse_file_with_no_vuln_has_no_findings(self):
1717
self.parse_file_with_no_vuln_has_no_findings()
1818

19+
def test_parse_file_with_multiple_ports_for_same_qid(self):
20+
with (get_unit_tests_scans_path("qualys") / "test_qualys.xml").open(encoding = "utf-8") as testfile:
21+
parser = QualysParser()
22+
findings = parser.get_findings(testfile,Test())
23+
24+
self.assertEqual(len(findings),2,"Should have 2 findings for different ports")
25+
ports = [self.get_unsaved_locations(f)[0].port for f in findings]
26+
self.assertIn(80,ports)
27+
self.assertIn(443,ports)
28+
29+
self.assertEqual(findings[0].title,findings[1].title)
30+
self.assertNotEqual(
31+
self.get_unsaved_locations(findings[0])[0].port,
32+
self.get_unsaved_locations(findings[1])[0].port
33+
)
34+
1935
def parse_file_with_no_vuln_has_no_findings(self):
2036
with (
2137
get_unit_tests_scans_path("qualys") / "empty.xml").open(encoding="utf-8",

0 commit comments

Comments
 (0)