diff --git a/docs/content/en/open_source/contributing/how-to-write-a-parser.md b/docs/content/en/open_source/contributing/how-to-write-a-parser.md index 26fea0bc240..3c0fcfe53a9 100644 --- a/docs/content/en/open_source/contributing/how-to-write-a-parser.md +++ b/docs/content/en/open_source/contributing/how-to-write-a-parser.md @@ -197,7 +197,7 @@ Example of use: from cvss import CVSS2, CVSS3, CVSS4 # TEMPORARY: Use Defect Dojo implementation of `parse_cvss_from_text` white waiting for https://github.com/RedHatProductSecurity/cvss/pull/75 to be released - vectors = dojo.utils.parse_cvss_from_text("CVSS:3.0/S:C/C:H/I:H/A:N/AV:P/AC:H/PR:H/UI:R/E:H/RL:O/RC:R/CR:H/IR:X/AR:X/MAC:H/MPR:X/MUI:X/MC:L/MA:X") + vectors = cvss.parser.parse_cvss_from_text("CVSS:3.0/S:C/C:H/I:H/A:N/AV:P/AC:H/PR:H/UI:R/E:H/RL:O/RC:R/CR:H/IR:X/AR:X/MAC:H/MPR:X/MUI:X/MC:L/MA:X") if len(vectors) > 0 and type(vectors[0]) is CVSS3: print(vectors[0].severities()) # this is the 3 severities diff --git a/dojo/utils.py b/dojo/utils.py index dc393babeca..991b6b84075 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -15,13 +15,14 @@ import bleach import crum +import cvss import hyperlink import vobject from asteval import Interpreter from auditlog.models import LogEntry from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cvss import CVSS2, CVSS3, CVSS4, CVSSError +from cvss import CVSS2, CVSS3, CVSS4 from dateutil.parser import parse from dateutil.relativedelta import MO, SU, relativedelta from django.conf import settings @@ -2660,49 +2661,11 @@ def generate_file_response_from_file_path( return response -# TEMPORARY: Local implementation until the upstream PR is merged & released: https://github.com/RedHatProductSecurity/cvss/pull/75 -def parse_cvss_from_text(text): - """ - Parses CVSS2, CVSS3, and CVSS4 vectors from arbitrary text and returns a list of CVSS objects. - - Parses text for substrings that look similar to CVSS vector - and feeds these matches to CVSS constructor. - - Args: - text (str): arbitrary text - - Returns: - A list of CVSS objects. - - """ - # Looks for substrings that resemble CVSS2, CVSS3, or CVSS4 vectors. - # CVSS3 and CVSS4 vectors start with a 'CVSS:x.x/' prefix and are matched by the optional non-capturing group. - # CVSS2 vectors do not include a prefix and are matched by raw vector pattern only. - # Minimum total match length is 26 characters to reduce false positives. - matches = re.compile(r"(?:CVSS:[3-4]\.\d/)?[A-Za-z:/]{26,}").findall(text) - - cvsss = set() - for match in matches: - try: - if match.startswith("CVSS:4."): - cvss = CVSS4(match) - elif match.startswith("CVSS:3."): - cvss = CVSS3(match) - else: - cvss = CVSS2(match) - - cvsss.add(cvss) - except (CVSSError, KeyError): - pass - - return list(cvsss) - - def parse_cvss_data(cvss_vector_string: str) -> dict: if not cvss_vector_string: return {} - vectors = parse_cvss_from_text(cvss_vector_string) + vectors = cvss.parser.parse_cvss_from_text(cvss_vector_string) if len(vectors) > 0: vector = vectors[0] # For CVSS2, environmental score is at index 2 diff --git a/dojo/validators.py b/dojo/validators.py index 8c5dc94d7de..aa3c4e5da5c 100644 --- a/dojo/validators.py +++ b/dojo/validators.py @@ -2,6 +2,7 @@ import re from collections.abc import Callable +import cvss from cvss import CVSS2, CVSS3, CVSS4 from django.core.exceptions import ValidationError from django.core.validators import FileExtensionValidator @@ -49,8 +50,7 @@ def clean_tags(value: str | list[str], exception_class: Callable = ValidationErr def cvss3_validator(value: str | list[str], exception_class: Callable = ValidationError) -> None: logger.debug("cvss3_validator called with value: %s", value) - from dojo.utils import parse_cvss_from_text - cvss_vectors = parse_cvss_from_text(value) + cvss_vectors = cvss.parser.parse_cvss_from_text(value) if len(cvss_vectors) > 0: vector_obj = cvss_vectors[0] @@ -76,8 +76,7 @@ def cvss3_validator(value: str | list[str], exception_class: Callable = Validati def cvss4_validator(value: str | list[str], exception_class: Callable = ValidationError) -> None: logger.debug("cvss4_validator called with value: %s", value) - from dojo.utils import parse_cvss_from_text - cvss_vectors = parse_cvss_from_text(value) + cvss_vectors = cvss.parser.parse_cvss_from_text(value) if len(cvss_vectors) > 0: vector_obj = cvss_vectors[0]