Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
43 changes: 3 additions & 40 deletions dojo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions dojo/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]

Expand All @@ -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]

Expand Down