Skip to content

Commit bc7c228

Browse files
Optimize CVSS parsing UI
Signed-off-by: Aryan-SINGH-GIT <aryansingh12oct2005@gmail.com>
1 parent 053c8fb commit bc7c228

File tree

5 files changed

+163
-34
lines changed

5 files changed

+163
-34
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from django.core.management.base import BaseCommand
2+
from vulnerabilities.models import VulnerabilitySeverity, AdvisorySeverity
3+
4+
class Command(BaseCommand):
5+
help = "Populate scoring_elements_data for VulnerabilitySeverity and AdvisorySeverity"
6+
7+
def handle(self, *args, **options):
8+
self.stdout.write("Starting population of VulnerabilitySeverity...")
9+
qs = VulnerabilitySeverity.objects.filter(scoring_elements__isnull=False)
10+
count = qs.count()
11+
self.stdout.write(f"Found {count} VulnerabilitySeverity records to process.")
12+
13+
for i, severity in enumerate(qs.iterator(chunk_size=1000), start=1):
14+
severity.save()
15+
if i % 1000 == 0:
16+
self.stdout.write(f"Processed {i}/{count} VulnerabilitySeverity records...")
17+
18+
self.stdout.write("Starting population of AdvisorySeverity...")
19+
qs = AdvisorySeverity.objects.filter(scoring_elements__isnull=False)
20+
count = qs.count()
21+
self.stdout.write(f"Found {count} AdvisorySeverity records to process.")
22+
23+
for i, severity in enumerate(qs.iterator(chunk_size=1000), start=1):
24+
severity.save()
25+
if i % 1000 == 0:
26+
self.stdout.write(f"Processed {i}/{count} AdvisorySeverity records...")
27+
28+
self.stdout.write("Population completed.")
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 5.2.11 on 2026-02-15 20:41
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('vulnerabilities', '0112_alter_advisoryseverity_scoring_system_and_more'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='advisoryseverity',
15+
name='scoring_elements_data',
16+
field=models.JSONField(blank=True, default=dict, help_text='Serialized scoring elements data.'),
17+
),
18+
migrations.AddField(
19+
model_name='vulnerabilityseverity',
20+
name='scoring_elements_data',
21+
field=models.JSONField(blank=True, default=dict, help_text='Serialized scoring elements data.'),
22+
),
23+
]

vulnerabilities/models.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,27 @@ class VulnerabilitySeverity(models.Model):
210210
"For example a CVSS vector string as used to compute a CVSS score.",
211211
)
212212

213+
scoring_elements_data = models.JSONField(
214+
default=dict,
215+
blank=True,
216+
help_text="Serialized scoring elements data.",
217+
)
218+
219+
def save(self, *args, **kwargs):
220+
if self.scoring_elements:
221+
try:
222+
scoring_system = SCORING_SYSTEMS.get(self.scoring_system)
223+
if scoring_system:
224+
self.scoring_elements_data = scoring_system.get(self.scoring_elements)
225+
except (
226+
CVSS2MalformedError,
227+
CVSS3MalformedError,
228+
CVSS4MalformedError,
229+
NotImplementedError,
230+
):
231+
pass
232+
super().save(*args, **kwargs)
233+
213234
published_at = models.DateTimeField(
214235
blank=True, null=True, help_text="UTC Date of publication of the vulnerability severity"
215236
)
@@ -2579,6 +2600,27 @@ class AdvisorySeverity(models.Model):
25792600
"For example a CVSS vector string as used to compute a CVSS score.",
25802601
)
25812602

2603+
scoring_elements_data = models.JSONField(
2604+
default=dict,
2605+
blank=True,
2606+
help_text="Serialized scoring elements data.",
2607+
)
2608+
2609+
def save(self, *args, **kwargs):
2610+
if self.scoring_elements:
2611+
try:
2612+
scoring_system = SCORING_SYSTEMS.get(self.scoring_system)
2613+
if scoring_system:
2614+
self.scoring_elements_data = scoring_system.get(self.scoring_elements)
2615+
except (
2616+
CVSS2MalformedError,
2617+
CVSS3MalformedError,
2618+
CVSS4MalformedError,
2619+
NotImplementedError,
2620+
):
2621+
pass
2622+
super().save(*args, **kwargs)
2623+
25822624
published_at = models.DateTimeField(
25832625
blank=True, null=True, help_text="UTC Date of publication of the vulnerability severity"
25842626
)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
from django.test import TestCase
3+
from vulnerabilities.models import VulnerabilitySeverity, AdvisorySeverity
4+
from vulnerabilities.severity_systems import SCORING_SYSTEMS
5+
6+
class TestSeverityStorage(TestCase):
7+
def test_scoring_elements_data_population_vulnerability(self):
8+
# CVSS v3.1 vector
9+
vector = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
10+
severity = VulnerabilitySeverity.objects.create(
11+
scoring_system="cvssv3.1",
12+
scoring_elements=vector,
13+
value="9.8"
14+
)
15+
severity.refresh_from_db()
16+
self.assertTrue(severity.scoring_elements_data)
17+
self.assertEqual(severity.scoring_elements_data['version'], '3.1')
18+
self.assertEqual(severity.scoring_elements_data['vectorString'], vector)
19+
20+
def test_scoring_elements_data_population_advisory(self):
21+
# CVSS v2 vector
22+
vector = "AV:N/AC:L/Au:N/C:P/I:P/A:P"
23+
severity = AdvisorySeverity.objects.create(
24+
scoring_system="cvssv2",
25+
scoring_elements=vector,
26+
value="7.5"
27+
)
28+
severity.refresh_from_db()
29+
self.assertTrue(severity.scoring_elements_data)
30+
self.assertEqual(severity.scoring_elements_data['version'], '2.0')
31+
self.assertEqual(severity.scoring_elements_data['vectorString'], vector)

vulnerabilities/views.py

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def get_queryset(self):
314314
Prefetch(
315315
"severities",
316316
queryset=models.VulnerabilitySeverity.objects.only(
317-
"scoring_system", "value", "url", "scoring_elements", "published_at"
317+
"scoring_system", "value", "url", "scoring_elements", "scoring_elements_data", "published_at"
318318
),
319319
),
320320
Prefetch(
@@ -347,21 +347,22 @@ def get_context_data(self, **kwargs):
347347
severity_vectors = []
348348

349349
for severity in valid_severities:
350-
try:
351-
vector_values_system = SCORING_SYSTEMS[severity.scoring_system]
352-
if not vector_values_system:
353-
logging.error(f"Unknown scoring system: {severity.scoring_system}")
354-
continue
355-
vector_values = vector_values_system.get(severity.scoring_elements)
356-
if vector_values:
357-
severity_vectors.append({"vector": vector_values, "origin": severity.url})
358-
except (
359-
CVSS2MalformedError,
360-
CVSS3MalformedError,
361-
CVSS4MalformedError,
362-
NotImplementedError,
363-
):
364-
logging.error(f"CVSSMalformedError for {severity.scoring_elements}")
350+
vector_values = severity.scoring_elements_data
351+
if not vector_values and severity.scoring_elements:
352+
try:
353+
vector_values_system = SCORING_SYSTEMS.get(severity.scoring_system)
354+
if vector_values_system:
355+
vector_values = vector_values_system.get(severity.scoring_elements)
356+
except (
357+
CVSS2MalformedError,
358+
CVSS3MalformedError,
359+
CVSS4MalformedError,
360+
NotImplementedError,
361+
):
362+
logging.error(f"CVSSMalformedError for {severity.scoring_elements}")
363+
364+
if vector_values:
365+
severity_vectors.append({"vector": vector_values, "origin": severity.url})
365366

366367
epss_severity = vulnerability.severities.filter(scoring_system="epss").first()
367368
epss_data = None
@@ -427,7 +428,7 @@ def get_queryset(self):
427428
Prefetch(
428429
"severities",
429430
queryset=models.AdvisorySeverity.objects.only(
430-
"scoring_system", "value", "url", "scoring_elements", "published_at"
431+
"scoring_system", "value", "url", "scoring_elements", "scoring_elements_data", "published_at"
431432
),
432433
),
433434
Prefetch(
@@ -494,23 +495,27 @@ def get_context_data(self, **kwargs):
494495
severity_vectors = []
495496

496497
for severity in valid_severities:
497-
try:
498-
vector_values_system = SCORING_SYSTEMS.get(severity.scoring_system)
499-
if not vector_values_system:
500-
logging.error(f"Unknown scoring system: {severity.scoring_system}")
501-
continue
502-
if vector_values_system.identifier in ["cvssv3.1_qr"]:
503-
continue
504-
vector_values = vector_values_system.get(severity.scoring_elements)
505-
if vector_values:
506-
severity_vectors.append({"vector": vector_values, "origin": severity.url})
507-
except (
508-
CVSS2MalformedError,
509-
CVSS3MalformedError,
510-
CVSS4MalformedError,
511-
NotImplementedError,
512-
):
513-
logging.error(f"CVSSMalformedError for {severity.scoring_elements}")
498+
vector_values_system = SCORING_SYSTEMS.get(severity.scoring_system)
499+
if not vector_values_system:
500+
logging.error(f"Unknown scoring system: {severity.scoring_system}")
501+
continue
502+
if vector_values_system.identifier in ["cvssv3.1_qr"]:
503+
continue
504+
505+
vector_values = severity.scoring_elements_data
506+
if not vector_values and severity.scoring_elements:
507+
try:
508+
vector_values = vector_values_system.get(severity.scoring_elements)
509+
except (
510+
CVSS2MalformedError,
511+
CVSS3MalformedError,
512+
CVSS4MalformedError,
513+
NotImplementedError,
514+
):
515+
logging.error(f"CVSSMalformedError for {severity.scoring_elements}")
516+
517+
if vector_values:
518+
severity_vectors.append({"vector": vector_values, "origin": severity.url})
514519

515520
def add_ssvc(ssvc):
516521
key = (ssvc.vector, ssvc.source_advisory_id)

0 commit comments

Comments
 (0)