Skip to content

Commit c7bc464

Browse files
damianprDamián Pardiñas Rodríguez
andauthored
Add new parser - Legitify (#10797)
* feat: added Legitify parser * style: quality fix * feat: updated .settings.dist.py * feat: updated .settings.dist.py --------- Co-authored-by: Damián Pardiñas Rodríguez <damian@MacBook-Pro-de-Damian.local>
1 parent 2a42b01 commit c7bc464

9 files changed

Lines changed: 2809 additions & 1 deletion

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
title: "Legitify"
3+
toc_hide: true
4+
---
5+
### File Types
6+
This DefectDojo parser accepts JSON files (in flattened format) from Legitify. For further details regarding the results, please consult the relevant [documentation](https://github.com/Legit-Labs/legitify?tab=readme-ov-file#output-options).
7+
8+
### Sample Scan Data
9+
Sample scan data for testing purposes can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/legitify).
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
38096a82c7cdeec6ca9c663c1ec3d6a5692a0e7bbfdea8fd2f05c58f753430d4
1+
71285f56a01869df55a802d79343f43c2e6a42ed52c4bb3591202e62b8569c64

dojo/settings/settings.dist.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,7 @@ def saml2_attrib_map_format(dict):
12771277
"Kiuwan SCA Scan": ["description", "severity", "component_name", "component_version", "cwe"],
12781278
"Rapplex Scan": ["title", "endpoints", "severity"],
12791279
"AppCheck Web Application Scanner": ["title", "severity"],
1280+
"Legitify Scan": ["title", "endpoints", "severity"],
12801281
}
12811282

12821283
# Override the hardcoded settings here via the env var
@@ -1499,6 +1500,7 @@ def saml2_attrib_map_format(dict):
14991500
"Kiuwan SCA Scan": DEDUPE_ALGO_HASH_CODE,
15001501
"Rapplex Scan": DEDUPE_ALGO_HASH_CODE,
15011502
"AppCheck Web Application Scanner": DEDUPE_ALGO_HASH_CODE,
1503+
"Legitify Scan": DEDUPE_ALGO_HASH_CODE,
15021504
}
15031505

15041506
# Override the hardcoded settings here via the env var

dojo/tools/legitify/__init__.py

Whitespace-only changes.

dojo/tools/legitify/parser.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import json
2+
3+
from dojo.models import Endpoint, Finding
4+
5+
6+
class LegitifyParser:
7+
8+
def get_scan_types(self):
9+
return ["Legitify Scan"]
10+
11+
def get_label_for_scan_types(self, scan_type):
12+
return scan_type # no custom label for now
13+
14+
def get_description_for_scan_types(self, scan_type):
15+
return "Legitify output file can be imported in JSON format."
16+
17+
def severity_mapper(self, severity):
18+
mapping = {
19+
"LOW": "Low",
20+
"MEDIUM": "Medium",
21+
"HIGH": "High",
22+
"CRITICAL": "Critical",
23+
}
24+
return mapping.get(severity, "Low")
25+
26+
def parse_json(self, file):
27+
try:
28+
data = file.read()
29+
try:
30+
tree = json.loads(str(data, "utf-8"))
31+
except Exception:
32+
tree = json.loads(data)
33+
except Exception:
34+
msg = "Invalid format"
35+
raise ValueError(msg)
36+
return tree
37+
38+
def get_findings(self, file, test):
39+
report_tree = self.parse_json(file)
40+
41+
findings = []
42+
for content_key, content_value in report_tree.get("content", {}).items():
43+
policy_info = content_value.get("policyInfo", {})
44+
is_finding = False
45+
endpoints = set()
46+
references = set()
47+
for violation in content_value.get("violations", []):
48+
if violation.get("status", None) == "FAILED":
49+
is_finding = True
50+
url = violation.get("canonicalLink", None)
51+
if url:
52+
references.add(url)
53+
endpoints.add(Endpoint.from_uri(url))
54+
55+
if is_finding:
56+
finding = Finding(
57+
description=policy_info.get("description", ""),
58+
dynamic_finding=False,
59+
impact="\n".join(policy_info.get("threat", [])),
60+
mitigation="\n".join(policy_info.get("remediationSteps", [])),
61+
references="\n".join(references),
62+
severity=self.severity_mapper(policy_info.get("severity", "LOW")),
63+
static_finding=True,
64+
title=f'{policy_info.get("namespace", "").capitalize()} | {policy_info.get("title", "")}',
65+
vuln_id_from_tool=policy_info.get("policyName", None),
66+
)
67+
finding.unsaved_endpoints = list(endpoints)
68+
findings.append(finding)
69+
return findings

0 commit comments

Comments
 (0)