Skip to content

Commit f275535

Browse files
committed
feat: implement IriusRisk CSV threat parser
Authored by T. Walker - DefectDojo
1 parent 5ee94af commit f275535

1 file changed

Lines changed: 74 additions & 1 deletion

File tree

dojo/tools/iriusrisk/parser.py

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
import csv
2+
import hashlib
3+
import io
4+
5+
from dojo.models import Finding
6+
7+
SEVERITY_MAPPING = {
8+
"Very low": "Info",
9+
"Low": "Low",
10+
"Medium": "Medium",
11+
"High": "High",
12+
}
13+
14+
115
class IriusriskParser:
216

317
def get_scan_types(self):
@@ -10,4 +24,63 @@ def get_description_for_scan_types(self, scan_type):
1024
return "Import IriusRisk threat model CSV exports."
1125

1226
def get_findings(self, filename, test):
13-
return []
27+
content = filename.read()
28+
if isinstance(content, bytes):
29+
content = content.decode("utf-8")
30+
reader = csv.DictReader(io.StringIO(content), delimiter=",", quotechar='"')
31+
findings = []
32+
for row in reader:
33+
component = (row.get("Component") or "").strip()
34+
use_case = (row.get("Use case") or "").strip()
35+
source = (row.get("Source") or "").strip()
36+
threat = (row.get("Threat") or "").strip()
37+
risk_response = (row.get("Risk Response") or "").strip()
38+
inherent_risk = (row.get("Inherent Risk") or "").strip()
39+
current_risk = (row.get("Current Risk") or "").strip()
40+
countermeasure_progress = (row.get("Countermeasure progress") or "").strip()
41+
weakness_tests = (row.get("Weakness tests") or "").strip()
42+
countermeasure_tests = (row.get("Countermeasure tests") or "").strip()
43+
projected_risk = (row.get("Projected Risk") or "").strip()
44+
owner = (row.get("Owner") or "").strip()
45+
46+
# Title: truncate to 150 chars with ellipsis if needed
47+
title = threat[:147] + "..." if len(threat) > 150 else threat
48+
49+
severity = SEVERITY_MAPPING.get(current_risk, "Info")
50+
51+
# Build description with all available fields
52+
description_parts = [
53+
f"**Threat:** {threat}",
54+
f"**Component:** {component}",
55+
f"**Use Case:** {use_case}",
56+
f"**Source:** {source}",
57+
f"**Inherent Risk:** {inherent_risk}",
58+
f"**Current Risk:** {current_risk}",
59+
f"**Projected Risk:** {projected_risk}",
60+
f"**Countermeasure Progress:** {countermeasure_progress}",
61+
f"**Weakness Tests:** {weakness_tests}",
62+
f"**Countermeasure Tests:** {countermeasure_tests}",
63+
]
64+
if owner:
65+
description_parts.append(f"**Owner:** {owner}")
66+
description = "\n".join(description_parts)
67+
68+
# Unique ID for deduplication across reimports
69+
unique_id = hashlib.sha256(
70+
f"{component}|{threat}|{risk_response}".encode(),
71+
).hexdigest()
72+
73+
finding = Finding(
74+
test=test,
75+
title=title,
76+
severity=severity,
77+
description=description,
78+
mitigation=risk_response,
79+
component_name=component,
80+
active=current_risk != "Very low",
81+
static_finding=True,
82+
dynamic_finding=False,
83+
unique_id_from_tool=unique_id,
84+
)
85+
findings.append(finding)
86+
return findings

0 commit comments

Comments
 (0)