Skip to content

Commit

Permalink
Merge pull request #1636 from aboutcode-org/1597-refactor-vulnerabili…
Browse files Browse the repository at this point in the history
…ty-severity

Refactor severity score model and fix incorrect suse scores
  • Loading branch information
keshav-space authored Nov 13, 2024
2 parents 8a68c97 + a008c37 commit 8bca5cc
Show file tree
Hide file tree
Showing 17 changed files with 401 additions and 178 deletions.
31 changes: 27 additions & 4 deletions vulnerabilities/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,25 @@ def to_representation(self, instance):


class VulnerabilityReferenceSerializer(serializers.ModelSerializer):
scores = VulnerabilitySeveritySerializer(many=True, source="vulnerabilityseverity_set")
scores = serializers.SerializerMethodField()
reference_url = serializers.CharField(source="url")

class Meta:
model = VulnerabilityReference
fields = ["reference_url", "reference_id", "reference_type", "scores", "url"]

def get_scores(self, instance):
severities_related_to_reference = [
severity
for severity in self.context.get("severities", [])
if severity.url == instance.url
]

return VulnerabilitySeveritySerializer(
severities_related_to_reference,
many=True,
).data


class BaseResourceSerializer(serializers.HyperlinkedModelSerializer):
"""
Expand Down Expand Up @@ -199,8 +211,7 @@ class VulnerabilitySerializer(BaseResourceSerializer):
many=True, source="filtered_fixed_packages", read_only=True
)
affected_packages = MinimalPackageSerializer(many=True, read_only=True)

references = VulnerabilityReferenceSerializer(many=True, source="vulnerabilityreference_set")
references = serializers.SerializerMethodField()
aliases = AliasSerializer(many=True, source="alias")
exploits = ExploitSerializer(many=True, read_only=True)
weaknesses = WeaknessSerializer(many=True)
Expand All @@ -214,10 +225,22 @@ def to_representation(self, instance):

return data

def get_references(self, vulnerability):
references = vulnerability.vulnerabilityreference_set.all()
severities = vulnerability.severities.all()

serialized_references = VulnerabilityReferenceSerializer(
references,
context={"severities": severities},
many=True,
).data

return serialized_references

def get_severity_range_score(self, instance):
severity_vectors = []
severity_values = set()
for s in instance.severities:
for s in instance.severities.all():
if s.scoring_system == EPSS.identifier:
continue

Expand Down
9 changes: 4 additions & 5 deletions vulnerabilities/api_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,10 @@ class Meta:

class V2VulnerabilitySeveritySerializer(ModelSerializer):
score = CharField(source="value")
reference = V2VulnerabilityReferenceSerializer()

class Meta:
model = VulnerabilitySeverity
fields = ("score", "scoring_system", "scoring_elements", "published_at", "reference")
fields = ("url", "score", "scoring_system", "scoring_elements", "published_at")


class V2WeaknessSerializer(ModelSerializer):
Expand Down Expand Up @@ -127,9 +126,9 @@ class V2VulnerabilitySerializer(ModelSerializer):

aliases = SerializerMethodField("get_aliases")
weaknesses = V2WeaknessSerializer(many=True, source="weaknesses_set")
scores = V2VulnerabilitySeveritySerializer(many=True, source="vulnerabilityseverity_set")
references = V2VulnerabilityReferenceSerializer(many=True, source="vulnerabilityreference_set")
exploits = V2ExploitSerializer(many=True, source="weaknesses")
severities = V2VulnerabilitySeveritySerializer(many=True)

def get_aliases(self, vulnerability):
return vulnerability.aliases.only("alias").values_list("alias", flat=True)
Expand All @@ -145,11 +144,11 @@ class Meta:
"vulnerability_id",
"aliases",
"status",
"scores",
"weaknesses",
"summary",
"exploits",
"references",
"severities",
)


Expand Down Expand Up @@ -358,7 +357,7 @@ def get_queryset(self):
.get_queryset()
.prefetch_related(
"weaknesses",
# "severities",
"severities",
# "exploits",
)
)
Expand Down
19 changes: 14 additions & 5 deletions vulnerabilities/api_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from rest_framework.response import Response
from rest_framework.reverse import reverse

from vulnerabilities.api import VulnerabilitySeveritySerializer
from vulnerabilities.models import Package
from vulnerabilities.models import Vulnerability
from vulnerabilities.models import VulnerabilityReference
Expand Down Expand Up @@ -41,11 +40,24 @@ class Meta:
fields = ["url", "reference_type", "reference_id"]


class VulnerabilitySeverityV2Serializer(serializers.ModelSerializer):
class Meta:
model = VulnerabilitySeverity
fields = ["url", "value", "scoring_system", "scoring_elements", "published_at"]

def to_representation(self, instance):
data = super().to_representation(instance)
published_at = data.get("published_at", None)
if not published_at:
data.pop("published_at")
return data


class VulnerabilityV2Serializer(serializers.ModelSerializer):
aliases = serializers.SerializerMethodField()
weaknesses = WeaknessV2Serializer(many=True)
references = VulnerabilityReferenceV2Serializer(many=True, source="vulnerabilityreference_set")
severities = VulnerabilitySeveritySerializer(many=True)
severities = VulnerabilitySeverityV2Serializer(many=True)

class Meta:
model = Vulnerability
Expand All @@ -61,9 +73,6 @@ class Meta:
def get_aliases(self, obj):
return [alias.alias for alias in obj.aliases.all()]

def get_severities(self, obj):
return obj.severities


class VulnerabilityListSerializer(serializers.ModelSerializer):
url = serializers.SerializerMethodField()
Expand Down
25 changes: 14 additions & 11 deletions vulnerabilities/import_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,33 +180,36 @@ def process_inferences(inferences: List[Inference], advisory: Advisory, improver
reference_id=ref.reference_id,
url=ref.url,
)
if not reference:
continue

VulnerabilityRelatedReference.objects.update_or_create(
reference=reference,
vulnerability=vulnerability,
)
if reference:
VulnerabilityRelatedReference.objects.update_or_create(
reference=reference,
vulnerability=vulnerability,
)
updated = False
for severity in ref.severities:
try:
published_at = str(severity.published_at) if severity.published_at else None
_vs, updated = VulnerabilitySeverity.objects.update_or_create(
(
vulnerability_severity,
updated,
) = VulnerabilitySeverity.objects.update_or_create(
scoring_system=severity.system.identifier,
reference=reference,
url=ref.url,
value=severity.value,
scoring_elements=severity.scoring_elements,
defaults={
"value": str(severity.value),
"scoring_elements": str(severity.scoring_elements),
"published_at": published_at,
},
)
vulnerability.severities.add(vulnerability_severity)
except:
logger.error(
f"Failed to create VulnerabilitySeverity for: {severity} with error:\n{traceback_format_exc()}"
)
if updated:
logger.info(
f"Severity updated for reference {ref!r} to value: {severity.value!r} "
f"Severity updated for reference {ref.url!r} to value: {severity.value!r} "
f"and scoring_elements: {severity.scoring_elements!r}"
)

Expand Down
16 changes: 4 additions & 12 deletions vulnerabilities/management/commands/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,12 @@


def serialize_severity(sev):
# inlines refs
ref = sev.reference
sevref = {
"url": ref.url,
"reference_type": ref.reference_type,
"reference_id": ref.reference_id,
}

return {
"score": sev.value,
"scoring_system": sev.scoring_system,
"scoring_elements": sev.scoring_elements,
"published_at": sev.published_at,
"reference": sevref,
"url": sev.url,
}


Expand All @@ -44,7 +36,7 @@ def serialize_vulnerability(vuln):
Return a plain data mapping seralized from ``vuln`` Vulnerability instance.
"""
aliases = list(vuln.aliases.values_list("alias", flat=True))
severities = [serialize_severity(sev) for sev in vuln.severities]
severities = [serialize_severity(sev) for sev in vuln.severities.all()]
weaknesses = [wkns.cwe for wkns in vuln.weaknesses.all()]

references = list(
Expand Down Expand Up @@ -161,11 +153,11 @@ def packages_by_type_ns_name():
"affected_by_vulnerabilities",
"affected_by_vulnerabilities__references",
"affected_by_vulnerabilities__weaknesses",
"affected_by_vulnerabilities__references__vulnerabilityseverity_set",
"affected_by_vulnerabilities__severities",
"fixing_vulnerabilities",
"fixing_vulnerabilities__references",
"fixing_vulnerabilities__weaknesses",
"fixing_vulnerabilities__references__vulnerabilityseverity_set",
"fixing_vulnerabilities__severities",
)
.paginated()
)
Expand Down
Loading

0 comments on commit 8bca5cc

Please sign in to comment.