Skip to content

Commit e900afe

Browse files
committed
Add exception for s.scoring_system when is not in SCORING_SYSTEMS
Add a get serverity values test Resolve merge conflict Change the style of cvss_printer display Add a new filter to print cvss vectors Change the table heading to Vertical Add support for CVSS vectors display Signed-off-by: ziadhany <ziadhany2016@gmail.com>
1 parent 5092a79 commit e900afe

6 files changed

Lines changed: 200 additions & 0 deletions

File tree

vulnerabilities/severity_systems.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ def compute(self, scoring_elements: str) -> str:
3737
"""
3838
return NotImplementedError
3939

40+
def get(self, scoring_elements: str):
41+
return NotImplementedError
42+
4043

4144
@dataclasses.dataclass(order=True)
4245
class Cvssv2ScoringSystem(ScoringSystem):
@@ -49,6 +52,10 @@ def compute(self, scoring_elements: str) -> str:
4952
"""
5053
return str(CVSS2(vector=scoring_elements).base_score)
5154

55+
def get(self, scoring_elements: str) -> dict:
56+
scoring_elements = scoring_elements.strip()
57+
return CVSS2(vector=scoring_elements).as_json()
58+
5259

5360
CVSSV2 = Cvssv2ScoringSystem(
5461
identifier="cvssv2",
@@ -71,6 +78,10 @@ def compute(self, scoring_elements: str) -> str:
7178
"""
7279
return str(CVSS3(vector=scoring_elements).base_score)
7380

81+
def get(self, scoring_elements: str) -> dict:
82+
scoring_elements = scoring_elements.strip()
83+
return CVSS3(vector=scoring_elements).as_json()
84+
7485

7586
CVSSV3 = Cvssv3ScoringSystem(
7687
identifier="cvssv3",

vulnerabilities/templates/vulnerability_details.html

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{% extends "base.html" %}
2+
{% load show_cvss %}
23
{% load humanize %}
34
{% load widget_tweaks %}
45
{% load static %}
@@ -52,6 +53,13 @@
5253
</span>
5354
</a>
5455
</li>
56+
<li data-tab="severities-vectors">
57+
<a>
58+
<span>
59+
Severities vectors ({{ severity_vectors|length }})
60+
</span>
61+
</a>
62+
</li>
5563
</ul>
5664
</div>
5765
<div id="tab-content">
@@ -297,6 +305,63 @@
297305
</table>
298306
</div>
299307

308+
<div class="tab-div content" data-content="severities-vectors">
309+
{% for severity_vector in severity_vectors %}
310+
{% if severity_vector.version == '2.0' %}
311+
Vector: {{ severity_vector.vectorString }}
312+
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth gray-header-border">
313+
<tr>
314+
<th>Exploitability (E)</th>
315+
<th>Access Vector (AV)</th>
316+
<th>Access Complexity (AC)</th>
317+
<th>Authentication (Au)</th>
318+
<th>Confidentiality Impact (C)</th>
319+
<th>Integrity Impact (I)</th>
320+
<th>Availability Impact (A)</th>
321+
</tr>
322+
<tr>
323+
<td>{{ severity_vector.exploitability|cvss_printer:"high,functional,unproven,proof_of_concept,not_defined" }}</td>
324+
<td>{{ severity_vector.accessVector|cvss_printer:"local,adjacent_network,network" }}</td>
325+
<td>{{ severity_vector.accessComplexity|cvss_printer:"high,medium,low" }}</td>
326+
<td>{{ severity_vector.authentication|cvss_printer:"multiple,single,none" }}</td>
327+
<td>{{ severity_vector.confidentialityImpact|cvss_printer:"none,partial,complete" }}</td>
328+
<td>{{ severity_vector.integrityImpact|cvss_printer:"none,partial,complete" }}</td>
329+
<td>{{ severity_vector.availabilityImpact|cvss_printer:"none,partial,complete" }}</td>
330+
</tr>
331+
</table>
332+
{% elif severity_vector.version == '3.1' or severity_vector.version == '3.0'%}
333+
Vector: {{ severity_vector.vectorString }}
334+
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth gray-header-border">
335+
<tr>
336+
<th>Attack Vector (AV)</th>
337+
<th>Attack Complexity (AC)</th>
338+
<th>Privileges Required (PR)</th>
339+
<th>User Interaction (UI)</th>
340+
<th>Scope (S)</th>
341+
<th>Confidentiality Impact (C)</th>
342+
<th>Integrity Impact (I)</th>
343+
<th>Availability Impact (A)</th>
344+
</tr>
345+
<tr>
346+
<td>{{ severity_vector.attackVector|cvss_printer:"network,adjacent_network,local,physical"}}</td>
347+
<td>{{ severity_vector.attackComplexity|cvss_printer:"low,high" }}</td>
348+
<td>{{ severity_vector.privilegesRequired|cvss_printer:"none,low,high" }}</td>
349+
<td>{{ severity_vector.userInteraction|cvss_printer:"none,required"}}</td>
350+
<td>{{ severity_vector.scope|cvss_printer:"unchanged,changed" }}</td>
351+
<td>{{ severity_vector.confidentialityImpact|cvss_printer:"high,low,none" }}</td>
352+
<td>{{ severity_vector.integrityImpact|cvss_printer:"high,low,none" }}</td>
353+
<td>{{ severity_vector.availabilityImpact|cvss_printer:"high,low,none" }}</td>
354+
</tr>
355+
</table>
356+
{% endif %}
357+
{% empty %}
358+
<tr>
359+
<td>
360+
There are no known CVSS vectors.
361+
</td>
362+
</tr>
363+
{% endfor %}
364+
</div>
300365
</div>
301366
</div>
302367
</section>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/nexB/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from django import template
2+
from django.utils.safestring import mark_safe
3+
4+
register = template.Library()
5+
6+
7+
@register.filter(is_safe=True)
8+
def cvss_printer(selected_vector, vector_values):
9+
"""highlight the selected vector value and return a list of paragraphs"""
10+
p_list = []
11+
selected_vector = selected_vector.lower()
12+
for vector_value in vector_values.split(","):
13+
if selected_vector == vector_value:
14+
p_list.append(f"<p class='has-text-black-bis mb-2'>{selected_vector}</p>")
15+
else:
16+
p_list.append(f"<p class='has-text-grey mb-2'>{vector_value}</p>")
17+
return mark_safe("".join(p_list))
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import pytest
2+
from cvss.exceptions import CVSS2MalformedError
3+
from cvss.exceptions import CVSS3MalformedError
4+
5+
from vulnerabilities.severity_systems import CVSSV2
6+
from vulnerabilities.severity_systems import CVSSV3
7+
8+
9+
def test_get_cvss2_vector_values():
10+
assert (
11+
CVSSV2.get("AV:N/AC:L/Au:N/C:P/I:N/A:N ")
12+
== CVSSV2.get("AV:N/AC:L/Au:N/C:P/I:N/A:N")
13+
== {
14+
"accessComplexity": "LOW",
15+
"accessVector": "NETWORK",
16+
"authentication": "NONE",
17+
"availabilityImpact": "NONE",
18+
"availabilityRequirement": "NOT_DEFINED",
19+
"baseScore": 5.0,
20+
"collateralDamagePotential": "NOT_DEFINED",
21+
"confidentialityImpact": "PARTIAL",
22+
"confidentialityRequirement": "NOT_DEFINED",
23+
"environmentalScore": 0.0,
24+
"exploitability": "NOT_DEFINED",
25+
"integrityImpact": "NONE",
26+
"integrityRequirement": "NOT_DEFINED",
27+
"remediationLevel": "NOT_DEFINED",
28+
"reportConfidence": "NOT_DEFINED",
29+
"targetDistribution": "NOT_DEFINED",
30+
"temporalScore": 0.0,
31+
"vectorString": "AV:N/AC:L/Au:N/C:P/I:N/A:N",
32+
"version": "2.0",
33+
}
34+
)
35+
36+
with pytest.raises(CVSS2MalformedError):
37+
CVSSV2.get("")
38+
39+
with pytest.raises(CVSS2MalformedError):
40+
CVSSV2.get("AV:N/AffgL/Au:N/C:P/I:N/A:N ")
41+
42+
43+
def test_get_cvss3_vector_values():
44+
assert (
45+
CVSSV3.get("CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H ")
46+
== CVSSV3.get("CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H")
47+
== {
48+
"attackComplexity": "LOW",
49+
"attackVector": "NETWORK",
50+
"availabilityImpact": "HIGH",
51+
"availabilityRequirement": "NOT_DEFINED",
52+
"baseScore": 9.1,
53+
"baseSeverity": "CRITICAL",
54+
"confidentialityImpact": "HIGH",
55+
"confidentialityRequirement": "NOT_DEFINED",
56+
"environmentalScore": 9.1,
57+
"environmentalSeverity": "CRITICAL",
58+
"exploitCodeMaturity": "NOT_DEFINED",
59+
"integrityImpact": "HIGH",
60+
"integrityRequirement": "NOT_DEFINED",
61+
"modifiedAttackComplexity": "LOW",
62+
"modifiedAttackVector": "NETWORK",
63+
"modifiedAvailabilityImpact": "HIGH",
64+
"modifiedConfidentialityImpact": "HIGH",
65+
"modifiedIntegrityImpact": "HIGH",
66+
"modifiedPrivilegesRequired": "HIGH",
67+
"modifiedUserInteraction": "NONE",
68+
"privilegesRequired": "HIGH",
69+
"remediationLevel": "NOT_DEFINED",
70+
"reportConfidence": "NOT_DEFINED",
71+
"scope": "CHANGED",
72+
"temporalScore": 9.1,
73+
"temporalSeverity": "CRITICAL",
74+
"userInteraction": "NONE",
75+
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H",
76+
"version": "3.1",
77+
}
78+
)
79+
80+
with pytest.raises(CVSS3MalformedError):
81+
CVSSV3.get("CVSS:3.7/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H ")
82+
83+
with pytest.raises(CVSS3MalformedError):
84+
CVSSV3.get("")

vulnerabilities/views.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
# See https://github.com/nexB/vulnerablecode for support or download.
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
9+
import logging
910

11+
from cvss.exceptions import CVSS2MalformedError
12+
from cvss.exceptions import CVSS3MalformedError
1013
from django.contrib import messages
1114
from django.core.exceptions import ValidationError
1215
from django.core.mail import send_mail
@@ -24,6 +27,7 @@
2427
from vulnerabilities.forms import PackageSearchForm
2528
from vulnerabilities.forms import VulnerabilitySearchForm
2629
from vulnerabilities.models import VulnerabilityStatusType
30+
from vulnerabilities.severity_systems import SCORING_SYSTEMS
2731
from vulnerabilities.utils import get_severity_range
2832
from vulnerablecode.settings import env
2933

@@ -124,6 +128,16 @@ def get_context_data(self, **kwargs):
124128
weakness_object for weakness_object in weaknesses if weakness_object.weakness
125129
]
126130
status = self.object.get_status_label
131+
132+
severity_vectors = []
133+
for s in self.object.severities:
134+
if s.scoring_elements and s.scoring_system in SCORING_SYSTEMS:
135+
try:
136+
vector_values = SCORING_SYSTEMS[s.scoring_system].get(s.scoring_elements)
137+
severity_vectors.append(vector_values)
138+
except (CVSS2MalformedError, CVSS3MalformedError, NotImplementedError):
139+
logging.error(f"CVSSMalformedError for {s.scoring_elements}")
140+
127141
context.update(
128142
{
129143
"vulnerability": self.object,
@@ -132,6 +146,7 @@ def get_context_data(self, **kwargs):
132146
"severity_score_range": get_severity_range(
133147
{s.value for s in self.object.severities}
134148
),
149+
"severity_vectors": severity_vectors,
135150
"references": self.object.references.all(),
136151
"aliases": self.object.aliases.all(),
137152
"affected_packages": self.object.affected_packages.all(),

0 commit comments

Comments
 (0)