|
2 | 2 | from datetime import datetime |
3 | 3 |
|
4 | 4 | import cvss |
| 5 | +from django.core.exceptions import ValidationError |
5 | 6 |
|
6 | 7 | from dojo.models import Endpoint |
7 | 8 |
|
@@ -96,7 +97,9 @@ def parse_screenshot_data(screenshot): |
96 | 97 |
|
97 | 98 |
|
98 | 99 | def get_screenshot_title(screenshot): |
99 | | - caption = screenshot.get("caption", "screenshot") |
| 100 | + raw_caption = screenshot.get("caption", "screenshot") |
| 101 | + # Screenshot filenames are limited to 100 characters. |
| 102 | + caption = f"{raw_caption[:94]}.." if len(raw_caption) > 96 else raw_caption |
100 | 103 | if not caption: |
101 | 104 | caption = "screenshot" |
102 | 105 | return f"{caption}{get_file_suffix_from_screenshot(screenshot)}" |
@@ -154,8 +157,17 @@ def get_attachement_title(attachment): |
154 | 157 | def parse_endpoints_from_hit(hit): |
155 | 158 | if "asset" not in hit or not hit["asset"]: |
156 | 159 | return [] |
157 | | - endpoint = Endpoint.from_uri(hit["asset"]) |
158 | | - return [endpoint] |
| 160 | + try: |
| 161 | + asset = hit.get("asset", None) |
| 162 | + if not asset: |
| 163 | + return [] |
| 164 | + # Workaround for Defect Dojo being silly when parsing uris. |
| 165 | + # If there's no protocol, it will assume the hostname is the protocol. |
| 166 | + asset = f"https://{asset}" if "://" not in asset else asset |
| 167 | + endpoint = Endpoint.from_uri(asset) |
| 168 | + except ValidationError: |
| 169 | + endpoint = None |
| 170 | + return [] if not endpoint else [endpoint] |
159 | 171 |
|
160 | 172 |
|
161 | 173 | def generate_test_description_from_report(data): |
@@ -185,3 +197,41 @@ def get_transformed_reference(reference): |
185 | 197 | return url |
186 | 198 | return None |
187 | 199 | return f"{title}: {url}" |
| 200 | + |
| 201 | + |
| 202 | +def parse_cwe_from_hit(hit): |
| 203 | + if "cwes" not in hit or not hit["cwes"]: |
| 204 | + return None |
| 205 | + cwes = hit["cwes"] |
| 206 | + # Grab the last CWE in the list, as it's sorted in numerical order, |
| 207 | + # and the last element is generally the most specific. |
| 208 | + return parse_cwe_id_from_cwe(cwes.pop()) if cwes and isinstance(cwes, list) and len(cwes) > 0 else None |
| 209 | + |
| 210 | + |
| 211 | +def parse_cwe_id_from_cwe(cwe): |
| 212 | + try: |
| 213 | + if not cwe: |
| 214 | + return None |
| 215 | + |
| 216 | + cwe_id = cwe.get("cwe_id", None) |
| 217 | + if not cwe_id: |
| 218 | + title = cwe.get("title", None) |
| 219 | + if not title: |
| 220 | + return None |
| 221 | + cwe_id = parse_cwe_id_from_cwe_title(title) |
| 222 | + elif isinstance(cwe_id, str): |
| 223 | + cwe_id = int(cwe_id) |
| 224 | + elif not isinstance(cwe_id, int): |
| 225 | + cwe_id = None |
| 226 | + except (ValueError, IndexError): |
| 227 | + return None |
| 228 | + return cwe_id |
| 229 | + |
| 230 | + |
| 231 | +def parse_cwe_id_from_cwe_title(title): |
| 232 | + try: |
| 233 | + if not title: |
| 234 | + return None |
| 235 | + return int(title.split("-")[1]) |
| 236 | + except (ValueError, IndexError): |
| 237 | + return None |
0 commit comments