Skip to content

Commit 94b5878

Browse files
committed
Add support to CVSSv4
Signed-off-by: ziadhany <[email protected]>
1 parent 474301d commit 94b5878

File tree

3 files changed

+104
-36
lines changed

3 files changed

+104
-36
lines changed

vulnerabilities/importers/nvd.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ def severities(self):
163163
"""
164164
severities = []
165165
impact = self.cve_item.get("impact") or {}
166+
base_metric_v4 = impact.get("baseMetricV4") or {}
167+
if base_metric_v4:
168+
cvss_v4 = base_metric_v4.get("cvssV4") or {}
169+
vs = VulnerabilitySeverity(
170+
system=severity_systems.CVSSV4,
171+
value=str(cvss_v4.get("baseScore") or ""),
172+
scoring_elements=str(cvss_v4.get("vectorString") or ""),
173+
)
174+
severities.append(vs)
175+
166176
base_metric_v3 = impact.get("baseMetricV3") or {}
167177
if base_metric_v3:
168178
cvss_v3 = get_item(base_metric_v3, "cvssV3")

vulnerabilities/severity_systems.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from cvss import CVSS2
1313
from cvss import CVSS3
14+
from cvss import CVSS4
1415

1516
"""
1617
Vulnerability scoring systems define scales, values and approach to score a
@@ -83,6 +84,22 @@ def get(self, scoring_elements: str) -> dict:
8384
return CVSS3(vector=scoring_elements).as_json()
8485

8586

87+
@dataclasses.dataclass(order=True)
88+
class Cvssv4ScoringSystem(ScoringSystem):
89+
def compute(self, scoring_elements: str) -> str:
90+
"""
91+
Return a CVSSv4 base score
92+
93+
>>> CVSSV4.compute('CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:N')
94+
'9.9'
95+
"""
96+
return str(CVSS4(vector=scoring_elements).base_score)
97+
98+
def get(self, scoring_elements: str) -> dict:
99+
scoring_elements = scoring_elements.strip()
100+
return CVSS4(vector=scoring_elements).as_json()
101+
102+
86103
CVSSV3 = Cvssv3ScoringSystem(
87104
identifier="cvssv3",
88105
name="CVSSv3 Base Score",
@@ -97,6 +114,13 @@ def get(self, scoring_elements: str) -> dict:
97114
notes="CVSSv3.1 base score and vector",
98115
)
99116

117+
CVSSV4 = Cvssv4ScoringSystem(
118+
identifier="cvssv4",
119+
name="CVSSv4 Base Score",
120+
url="https://www.first.org/cvss/v4-0/",
121+
notes="CVSSv4 base score and vector",
122+
)
123+
100124
REDHAT_BUGZILLA = ScoringSystem(
101125
identifier="rhbs",
102126
name="RedHat Bugzilla severity",
@@ -163,6 +187,7 @@ def get(self, scoring_elements: str) -> dict:
163187
CVSSV2,
164188
CVSSV3,
165189
CVSSV31,
190+
CVSSV4,
166191
REDHAT_BUGZILLA,
167192
REDHAT_AGGREGATE,
168193
ARCHLINUX,

vulnerabilities/templates/vulnerability_details.html

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -335,51 +335,85 @@
335335
<div class="tab-div content" data-content="severities-vectors">
336336
{% for severity_vector in severity_vectors %}
337337
{% if severity_vector.version == '2.0' %}
338-
Vector: {{ severity_vector.vectorString }}
339-
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth gray-header-border">
340-
<tr>
341-
<th>Exploitability (E)</th>
342-
<th>Access Vector (AV)</th>
343-
<th>Access Complexity (AC)</th>
344-
<th>Authentication (Au)</th>
345-
<th>Confidentiality Impact (C)</th>
346-
<th>Integrity Impact (I)</th>
347-
<th>Availability Impact (A)</th>
348-
</tr>
349-
<tr>
350-
<td>{{ severity_vector.exploitability|cvss_printer:"high,functional,unproven,proof_of_concept,not_defined" }}</td>
351-
<td>{{ severity_vector.accessVector|cvss_printer:"local,adjacent_network,network" }}</td>
352-
<td>{{ severity_vector.accessComplexity|cvss_printer:"high,medium,low" }}</td>
353-
<td>{{ severity_vector.authentication|cvss_printer:"multiple,single,none" }}</td>
354-
<td>{{ severity_vector.confidentialityImpact|cvss_printer:"none,partial,complete" }}</td>
355-
<td>{{ severity_vector.integrityImpact|cvss_printer:"none,partial,complete" }}</td>
356-
<td>{{ severity_vector.availabilityImpact|cvss_printer:"none,partial,complete" }}</td>
357-
</tr>
358-
</table>
359-
{% elif severity_vector.version == '3.1' or severity_vector.version == '3.0'%}
360338
Vector: {{ severity_vector.vectorString }}
361339
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth gray-header-border">
362340
<tr>
363-
<th>Attack Vector (AV)</th>
364-
<th>Attack Complexity (AC)</th>
365-
<th>Privileges Required (PR)</th>
366-
<th>User Interaction (UI)</th>
367-
<th>Scope (S)</th>
341+
<th>Exploitability (E)</th>
342+
<th>Access Vector (AV)</th>
343+
<th>Access Complexity (AC)</th>
344+
<th>Authentication (Au)</th>
368345
<th>Confidentiality Impact (C)</th>
369346
<th>Integrity Impact (I)</th>
370347
<th>Availability Impact (A)</th>
371348
</tr>
372349
<tr>
373-
<td>{{ severity_vector.attackVector|cvss_printer:"network,adjacent_network,local,physical"}}</td>
374-
<td>{{ severity_vector.attackComplexity|cvss_printer:"low,high" }}</td>
375-
<td>{{ severity_vector.privilegesRequired|cvss_printer:"none,low,high" }}</td>
376-
<td>{{ severity_vector.userInteraction|cvss_printer:"none,required"}}</td>
377-
<td>{{ severity_vector.scope|cvss_printer:"unchanged,changed" }}</td>
378-
<td>{{ severity_vector.confidentialityImpact|cvss_printer:"high,low,none" }}</td>
379-
<td>{{ severity_vector.integrityImpact|cvss_printer:"high,low,none" }}</td>
380-
<td>{{ severity_vector.availabilityImpact|cvss_printer:"high,low,none" }}</td>
350+
<td>{{ severity_vector.exploitability|cvss_printer:"high,functional,unproven,proof_of_concept,not_defined" }}</td>
351+
<td>{{ severity_vector.accessVector|cvss_printer:"local,adjacent_network,network" }}</td>
352+
<td>{{ severity_vector.accessComplexity|cvss_printer:"high,medium,low" }}</td>
353+
<td>{{ severity_vector.authentication|cvss_printer:"multiple,single,none" }}</td>
354+
<td>{{ severity_vector.confidentialityImpact|cvss_printer:"none,partial,complete" }}</td>
355+
<td>{{ severity_vector.integrityImpact|cvss_printer:"none,partial,complete" }}</td>
356+
<td>{{ severity_vector.availabilityImpact|cvss_printer:"none,partial,complete" }}</td>
381357
</tr>
382358
</table>
359+
{% elif severity_vector.version == '3.1' or severity_vector.version == '3.0'%}
360+
Vector: {{ severity_vector.vectorString }}
361+
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth gray-header-border">
362+
<tr>
363+
<th>Attack Vector (AV)</th>
364+
<th>Attack Complexity (AC)</th>
365+
<th>Privileges Required (PR)</th>
366+
<th>User Interaction (UI)</th>
367+
<th>Scope (S)</th>
368+
<th>Confidentiality Impact (C)</th>
369+
<th>Integrity Impact (I)</th>
370+
<th>Availability Impact (A)</th>
371+
</tr>
372+
<tr>
373+
<td>{{ severity_vector.attackVector|cvss_printer:"network,adjacent_network,local,physical"}}</td>
374+
<td>{{ severity_vector.attackComplexity|cvss_printer:"low,high" }}</td>
375+
<td>{{ severity_vector.privilegesRequired|cvss_printer:"none,low,high" }}</td>
376+
<td>{{ severity_vector.userInteraction|cvss_printer:"none,required"}}</td>
377+
<td>{{ severity_vector.scope|cvss_printer:"unchanged,changed" }}</td>
378+
<td>{{ severity_vector.confidentialityImpact|cvss_printer:"high,low,none" }}</td>
379+
<td>{{ severity_vector.integrityImpact|cvss_printer:"high,low,none" }}</td>
380+
<td>{{ severity_vector.availabilityImpact|cvss_printer:"high,low,none" }}</td>
381+
</tr>
382+
</table>
383+
{% elif severity_vector.version == '4' or severity_vector.version == '4'%}
384+
Vector: {{ severity_vector.vectorString }}
385+
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth gray-header-border">
386+
<tr>
387+
<th>Attack Vector (AV)</th>
388+
<th>Attack Complexity (AC)</th>
389+
<th>Attack Requirements (AT)</th>
390+
<th>Privileges Required (PR)</th>
391+
<th>User Interaction (UI)</th>
392+
393+
<th>Vulnerable System Impact Confidentiality (VC)</th>
394+
<th>Vulnerable System Impact Integrity (VI)</th>
395+
<th>Vulnerable System Impact Availability (VA)</th>
396+
397+
<th>Subsequent System Impact Confidentiality (SC)</th>
398+
<th>Subsequent System Impact Integrity (SI)</th>
399+
<th>Subsequent System Impact Availability (SA)</th>
400+
</tr>
401+
<tr>
402+
<td>{{ severity_vector.attackVector|cvss_printer:"network,adjacent,local,physical"}}</td>
403+
<td>{{ severity_vector.attackComplexity|cvss_printer:"low,high" }}</td>
404+
<td>{{ severity_vector.attackRequirement|cvss_printer:"none,present" }}</td>
405+
<td>{{ severity_vector.privilegesRequired|cvss_printer:"none,low,high" }}</td>
406+
<td>{{ severity_vector.userInteraction|cvss_printer:"none,passive,active"}}</td>
407+
408+
<td>{{ severity_vector.vulnerableSystemImpactConfidentiality|cvss_printer:"high,low,none" }}</td>
409+
<td>{{ severity_vector.vulnerableSystemImpactIntegrity|cvss_printer:"high,low,none" }}</td>
410+
<td>{{ severity_vector.vulnerableSystemImpactAvailability|cvss_printer:"high,low,none" }}</td>
411+
412+
<td>{{ severity_vector.subsequentSystemImpactConfidentiality|cvss_printer:"high,low,none" }}</td>
413+
<td>{{ severity_vector.subsequentSystemImpactIntegrity|cvss_printer:"high,low,none" }}</td>
414+
<td>{{ severity_vector.subsequentSystemImpactAvailability|cvss_printer:"high,low,none" }}</td>
415+
</tr>
416+
</table>
383417
{% endif %}
384418
{% empty %}
385419
<tr>
@@ -511,7 +545,6 @@
511545
{% endfor %}
512546
</table>
513547
</div>
514-
515548
</div>
516549
</div>
517550
</section>

0 commit comments

Comments
 (0)