Skip to content

Commit 7e7ecd3

Browse files
🎉 implement zora vulnerabilty parser (#13744)
* 🎉 implement zora vulnerabilty parser * udpate * update * update * fix * fix
1 parent 5a97ed6 commit 7e7ecd3

File tree

6 files changed

+593
-0
lines changed

6 files changed

+593
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
---
3+
title: "Zora Parser"
4+
toc_hide: true
5+
---
6+
Zora scan results can be exported from the [Zora platform](https://github.com/undistro/zora)
7+
8+
### Sample Scan Data
9+
Zora scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/zora).

dojo/tools/zora/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__author__ = "manuel-sommer"

dojo/tools/zora/parser.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
import csv
3+
import io
4+
5+
from dojo.models import Finding, Test
6+
7+
8+
class ZoraParser:
9+
10+
"""Parser for Zora combined CSV export."""
11+
12+
def get_scan_types(self):
13+
return ["Zora Parser"]
14+
15+
def get_label_for_scan_types(self, scan_type):
16+
return "Zora Parser"
17+
18+
def get_description_for_scan_types(self, scan_type):
19+
return "Zora Parser scan results in csv file format."
20+
21+
def get_findings(self, content, test: Test) -> list[Finding]:
22+
findings = []
23+
if hasattr(content, "read"):
24+
content = content.read()
25+
if isinstance(content, bytes):
26+
content = content.decode("utf-8")
27+
csv_reader = csv.DictReader(io.StringIO(content), delimiter=",", quotechar='"')
28+
for row in csv_reader:
29+
title = row.get("title")
30+
raw_severity = (row.get("severity") or "").strip().lower()
31+
severity_map = {
32+
"info": "Info",
33+
"informational": "Info",
34+
"low": "Low",
35+
"medium": "Medium",
36+
"med": "Medium",
37+
"high": "High",
38+
"critical": "Critical",
39+
"crit": "Critical",
40+
}
41+
severity = severity_map.get(raw_severity, "Info")
42+
description = f"**Source**: {row.get('source')}\n"
43+
description += f"**Image**: {row.get('image')}\n"
44+
description += f"**ID**: {row.get('id')}\n"
45+
description += f"**Details**: {row.get('description')}\n"
46+
if row.get("fixVersion"):
47+
description += f"**Fix Version**: {row.get('fixVersion')}\n"
48+
mitigation = row.get("description", "")
49+
unique_id = f"{row.get('source')}-{row.get('image')}-{row.get('id')}"
50+
status = row.get("status", "").upper()
51+
is_mitigated = status in {"PASS", "OK", "FIXED"}
52+
finding = Finding(
53+
title=title,
54+
description=description,
55+
severity=severity,
56+
mitigation=mitigation,
57+
static_finding=False,
58+
dynamic_finding=True,
59+
unique_id_from_tool=unique_id,
60+
test=test,
61+
is_mitigated=is_mitigated,
62+
)
63+
vuln_id = row.get("id")
64+
if vuln_id:
65+
finding.unsaved_vulnerability_ids = [vuln_id]
66+
findings.append(finding)
67+
return findings
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
source,checkID,title,severity,status,remediation

0 commit comments

Comments
 (0)