66from datetime import datetime
77from typing import ClassVar
88
9+ import cvss .parser
10+ from cvss .cvss3 import CVSS3
911from dateutil import parser as date_parser
1012from django .core .files .uploadedfile import TemporaryUploadedFile
13+ from django .utils import timezone
1114
1215from dojo .models import Finding , Test
1316
@@ -49,14 +52,39 @@ def get_vulnerability_disclosure_json_findings(self, tree, test):
4952 severity = "Info"
5053 except Exception :
5154 severity = "Info"
55+
56+ # Try to grab CVSS fields
57+ if cvssv3_score := content .get ("relationships" , {}).get ("severity" , {}).get ("data" , {}).get ("attributes" , {}).get ("score" ):
58+ description += f"CVSS: { cvssv3_score } \n "
59+
60+ cvssv3_vector = None
61+ if cvss_vector_string := content .get ("relationships" , {}).get ("severity" , {}).get ("data" , {}).get ("attributes" , {}).get ("cvss_vector_string" ):
62+ vectors = cvss .parser .parse_cvss_from_text (cvss_vector_string )
63+ if len (vectors ) > 0 and type (vectors [0 ]) is CVSS3 :
64+ cvssv3_vector = vectors [0 ].clean_vector ()
65+ if cvssv3_score is None :
66+ cvssv3_score = vectors [0 ].scores ()[0 ]
67+
5268 # Build the references of the Dojo finding
5369 ref_link = "https://hackerone.com/reports/{}" .format (
5470 content .get ("id" ),
5571 )
5672 references += f"[{ ref_link } ]({ ref_link } )"
5773
5874 # Set active state of the Dojo finding
59- active = content ["attributes" ]["state" ] in {"triaged" , "new" }
75+ active = True
76+ if "main_state" in content ["attributes" ]:
77+ active = content ["attributes" ]["main_state" ] != "closed"
78+ else :
79+ # If there is no main_state, we assume keep the old logic
80+ active = content ["attributes" ]["state" ] in {"triaged" , "new" }
81+
82+ is_mitigated = False
83+ mitigated = None
84+ if not active :
85+ is_mitigated = not active
86+ if is_mitigated :
87+ mitigated = date_parser .parse (content ["attributes" ]["closed_at" ]) if content ["attributes" ].get ("closed_at" ) else timezone .now ()
6088
6189 # Set CWE of the Dojo finding
6290 try :
@@ -84,15 +112,24 @@ def get_vulnerability_disclosure_json_findings(self, tree, test):
84112 date = date ,
85113 test = test ,
86114 active = active ,
115+ is_mitigated = is_mitigated ,
116+ mitigated = mitigated ,
87117 description = description ,
88118 severity = severity ,
89119 mitigation = "See description" ,
90120 impact = "No impact provided" ,
91121 references = references ,
92122 cwe = cwe ,
93123 dynamic_finding = False ,
124+ cvssv3 = cvssv3_vector ,
125+ cvssv3_score = cvssv3_score ,
94126 )
95127 finding .unsaved_endpoints = []
128+
129+ # Add vulnerability IDs if they are present
130+ if (cve_ids := content ["attributes" ].get ("cve_ids" )) is not None and len (cve_ids ) > 0 :
131+ finding .unsaved_vulnerability_ids = cve_ids
132+
96133 dupes [dupe_key ] = finding
97134 return list (dupes .values ())
98135
@@ -117,15 +154,30 @@ def build_description(self, content):
117154 )
118155 description += f"Triaged: { triaged_date } \n "
119156
120- # Try to grab CVSS
121- if cvss := content .get ("relationships" , {}).get ("severity" , {}).get ("data" , {}).get ("attributes" , {}).get ("score" ):
122- description += f"CVSS: { cvss } \n "
123-
124157 # Build rest of description meat
125158 description += "##Report: \n {}\n " .format (
126159 content ["attributes" ]["vulnerability_information" ],
127160 )
128161
162+ structured_scope_fields_to_label : dict [str , str ] = {
163+ "asset_identifier" : "Asset Identifier" ,
164+ "asset_type" : "Asset Type" ,
165+ "confidentiality_requirement" : "Confidentiality Requirement" ,
166+ "integrity_requirement" : "Integrity Requirement" ,
167+ "availability_requirement" : "Availability Requirement" ,
168+ "max_severity" : "Max Severity" ,
169+ "instruction" : "Instruction" ,
170+ "eligible_for_bounty" : "Eligible for Bounty" ,
171+ "eligible_for_submission" : "Eligible for Submission" ,
172+ "reference" : "Reference" ,
173+ }
174+
175+ if structured_scope_attributes := content .get ("relationships" , {}).get ("structured_scope" , {}).get ("data" , {}).get ("attributes" , {}):
176+ description += "\n ##Structured Scope:\n "
177+ for field , label in structured_scope_fields_to_label .items ():
178+ if (value := structured_scope_attributes .get (field )) is not None :
179+ description += f"**{ label } **: { value } \n "
180+
129181 # Try to grab weakness if it's there
130182 if weakness_title := content .get ("relationships" , {}).get ("weakness" , {}).get ("data" , {}).get ("attributes" , {}).get ("name" ):
131183 if weakness_desc := content .get ("relationships" , {}).get ("weakness" , {}).get ("data" , {}).get ("attributes" , {}).get ("description" ):
0 commit comments