Skip to content

Commit

Permalink
new: [webservice] Display severity informations for vulnerabilities f…
Browse files Browse the repository at this point in the history
…rom GitHub, NVD and Pysec.
  • Loading branch information
cedricbonhomme committed Aug 2, 2024
1 parent b1f7cd6 commit 56de1fb
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 1 deletion.
13 changes: 12 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ qrcode = "^7.4.2"
pyvariot = "^0.2.0"
markdown = "^3.6"
the-big-username-blacklist = "^1.5.4"
cvss = "^3.1"

[tool.poetry.group.dev.dependencies]
ipython = "^8.25.0"
Expand Down
41 changes: 41 additions & 0 deletions website/web/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from datetime import datetime
from dateutil.parser import parse # type: ignore[import-untyped]

import cvss
import markdown # type: ignore[import-untyped]
from flask import Flask
from flask_bootstrap import Bootstrap5 # type: ignore[import-untyped]
Expand Down Expand Up @@ -143,7 +144,47 @@ def hash(value: str) -> str:
return m.hexdigest()


def cvss_base_score(vector: str, version: str) -> str:
"""Returns the base code from a CVSS vector."""
if version in ["cvssV4_0", "CVSS_V4", "cvssV4_0"]:
c = cvss.CVSS4(vector)
return str(c.base_score)
elif version in ["cvssV3_0", "CVSS_V3", "cvssV3_1"]:
c = cvss.CVSS3(vector)
return ", ".join(
[str(score) for score in c.scores()[:1]]
) # slice the list to ignore temporal and environmental scores
return vector


def cvss_severity(vector: str, version: str) -> str:
"""Returns the severity from a CVSS vector."""
if version in ["cvssV4_0", "CVSS_V4", "cvssV4_0"]:
c = cvss.CVSS4(vector)
return str(c.severity)
elif version in ["cvssV3_0", "CVSS_V3", "cvssV3_1"]:
c = cvss.CVSS3(vector)
return ", ".join(
[str(score) for score in c.severities()[:1]]
) # slice the list to ignore temporal and environmental scores
return vector


def cvss_clean_vector(vector: str, version: str) -> str:
"""Returns a clean version of a vector."""
if version in ["cvssV4_0", "CVSS_V4", "cvssV4_0"]:
c = cvss.CVSS4(vector)
return c.clean_vector()
elif version in ["cvssV3_0", "CVSS_V3", "cvssV3_1"]:
c = cvss.CVSS3(vector)
return c.clean_vector()
return vector


application.jinja_env.filters["datetimeformat"] = datetimeformat
application.jinja_env.filters["string_to_datetime"] = string_to_datetime
application.jinja_env.filters["markdown"] = to_markdown
application.jinja_env.filters["hash"] = hash
application.jinja_env.filters["cvss_base_score"] = cvss_base_score
application.jinja_env.filters["cvss_severity"] = cvss_severity
application.jinja_env.filters["cvss_clean_vector"] = cvss_clean_vector
47 changes: 47 additions & 0 deletions website/web/templates/vulnerability_templates.html
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,29 @@ <h6 class="card-subtitle mb-2 text-body-secondary">
<div class="row">
<div class="col-md-2 fw-bold">Modified</div><div class="col">{{ vulnerability_data['cveMetadata']['dateUpdated'] | string_to_datetime('%Y-%m-%d %H:%M') }}</div>
</div>
{% if vulnerability_data['containers']['cna']['metrics'] %}
{% set severity_css = {"Low": "bg-success", "Medium": "bg-warning", "High": "bg-danger", "Critical": "bg-danger"} %}
<div class="row">
<div class="col-md-2 fw-bold">Severity</div>
<div class="col">
{% for metric in vulnerability_data['containers']['cna']['metrics'] %}
{% if 'cvssV3_1' in metric or 'cvssV3_0' in metric %}
{% if 'vectorString' in metric['cvssV3_1'] %}
{% set vectorString = metric['cvssV3_1']['vectorString'] %}
{% set version = 'cvssV3_1' %}
{% set version_short = '3.1' %}
{% endif %}
{% if 'vectorString' in metric['cvssV3_0'] %}
{% set vectorString = metric['cvssV3_0']['vectorString'] %}
{% set version = 'cvssV3_0' %}
{% set version_short = '3.0' %}
{% endif %}
<span class="{{ severity_css[vectorString | cvss_severity(version)] }}">{{ vectorString | cvss_base_score(version) }} ({{ vectorString | cvss_severity(version) }})</span> - CVSS_V3 - <a href="https://www.first.org/cvss/calculator/{{ version_short }}#{{ vectorString | cvss_clean_vector(version) }}" rel="noreferrer" target="_blank">{{ vectorString | cvss_clean_vector(version) }}</a><br />
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{% if vulnerability_data['containers']['cna']['title'] %}
<div class="row">
<div class="col-md-2 fw-bold">Summary</div><div class="col">{{vulnerability_data['containers']['cna']['title']}}</div>
Expand Down Expand Up @@ -167,6 +190,18 @@ <h6 class="card-subtitle mb-2 text-body-secondary">
<div class="row">
<div class="col-md-2 fw-bold">Modified</div><div class="col">{{ vulnerability_data['modified'] | string_to_datetime('%Y-%m-%d %H:%M') }}</div>
</div>
{% if 'severity' in vulnerability_data and vulnerability_data['severity'] %}
<div class="row">
<div class="col-md-2 fw-bold">Severity</div>
<div class="col">
{% set severity_css = {"Low": "bg-success", "Medium": "bg-warning", "High": "bg-danger", "Critical": "bg-danger"} %}
{% set versions = {"CVSS_V3": "3.1", "CVSS_V4": "4.0"} %}
{% for severity in vulnerability_data['severity'] %}
<span class="{{ severity_css[severity['score'] | cvss_severity(severity['type'])] }}">{{ severity['score'] | cvss_base_score(severity['type']) }} ({{ severity['score'] | cvss_severity(severity['type']) }})</span> - {{ severity['type'] }} - <a href="https://www.first.org/cvss/calculator/{{ versions[severity['type']] }}#{{ severity['score'] | cvss_clean_vector(severity['type']) }}" rel="noreferrer" target="_blank">{{ severity['score'] | cvss_clean_vector(severity['type']) }}</a><br />
{% endfor %}
</div>
</div>
{% endif %}
{% if 'summary' in vulnerability_data %}
<div class="row">
<div class="col-md-2 fw-bold">Summary</div><div class="col">{{ vulnerability_data['summary'] }}</div>
Expand Down Expand Up @@ -481,6 +516,18 @@ <h6 class="card-subtitle mb-2 text-body-secondary">
<div class="row">
<div class="col-md-2 fw-bold">Modified</div><div class="col">{{ vulnerability_data['modified'] | string_to_datetime('%Y-%m-%d %H:%M') }}</div>
</div>
{% if 'severity' in vulnerability_data and vulnerability_data['severity'] %}
<div class="row">
<div class="col-md-2 fw-bold">Severity</div>
<div class="col">
{% set severity_css = {"Low": "bg-success", "Medium": "bg-warning", "High": "bg-danger", "Critical": "bg-danger"} %}
{% set versions = {"CVSS_V3": "3.1", "CVSS_V4": "4.0"} %}
{% for severity in vulnerability_data['severity'] %}
<span class="{{ severity_css[severity['score'] | cvss_severity(severity['type'])] }}">{{ severity['score'] | cvss_base_score(severity['type']) }} ({{ severity['score'] | cvss_severity(severity['type']) }})</span> - {{ severity['type'] }} - <a href="https://www.first.org/cvss/calculator/{{ versions[severity['type']] }}#{{ severity['score'] | cvss_clean_vector(severity['type']) }}" rel="noreferrer" target="_blank">{{ severity['score'] | cvss_clean_vector(severity['type']) }}</a><br />
{% endfor %}
</div>
</div>
{% endif %}
<div class="row">
<div class="col-md-2 fw-bold">Details</div><div class="col">{{ vulnerability_data['details'] | markdown | safe }}</div>
</div>
Expand Down

0 comments on commit 56de1fb

Please sign in to comment.