Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 83 additions & 10 deletions vulnerabilities/templates/advisory_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

<div class="tabs is-boxed" id="tabs">
<ul>
<li class="is-active" data-tab="essentials">
<li class="{% if not 'epss_page' in request.GET %}is-active{% endif %}" data-tab="essentials">
<a>
<span>Essentials</span>
</a>
Expand Down Expand Up @@ -55,7 +55,7 @@
</li>
{% endif %}

<li data-tab="epss">
<li class="{% if 'epss_page' in request.GET %}is-active{% endif %}" data-tab="epss">
<a>
<span>
EPSS
Expand All @@ -80,7 +80,7 @@
</a>
</li>
{% endif %}

<li data-tab="patch-url">
<a>
<span>
Expand All @@ -90,17 +90,18 @@
</span>
</a>
</li>
<!-- <li data-tab="history">

{% comment %} <li data-tab="history">
<a>
<span>
History ({{ history|length }})
</span>
</a>
</li> -->
</li> {% endcomment %}
</ul>
</div>
<div id="tab-content">
<div class="tab-div is-active" data-content="essentials">
<div class="tab-div {% if not 'epss_page' in request.GET %}is-active{% endif %}" data-content="essentials">
<div class="tab-nested-div">
<table class="table vcio-table width-100-pct mt-2">
<tbody>
Expand Down Expand Up @@ -458,7 +459,7 @@
{% endfor %}
</div>

<div class="tab-div content" data-content="epss">
<div class="tab-div content {% if 'epss_page' in request.GET %}is-active{% endif %}" data-content="epss">
{% if epss_data %}
<div class="has-text-weight-bold tab-nested-div ml-1 mb-1 mt-1">
Exploit Prediction Scoring System (EPSS)
Expand Down Expand Up @@ -518,6 +519,68 @@
{% endif %}
</tbody>
</table>

{% if epss_history_data|length > 1 %}
<div class="has-text-weight-bold tab-nested-div ml-1 mb-3 mt-5">
EPSS Score History
</div>

<div class="mb-4 ml-1">
<button id="btn-load-epss-chart" class="button is-small is-info mr-2">
See Trend
</button>
<button id="btn-load-epss-table" class="button is-small is-info">
See Table
</button>
</div>

<div id="epss-chart-container" style="display:none;">
<div class="has-text-weight-bold tab-nested-div ml-1 mb-3">
30-Day Trend
</div>
<div id="epss-chart" style="width:100%; height:260px;"></div>
</div>

<div id="epss-history-table-container" class="mt-5" {% if not 'epss_page' in request.GET %}style="display:none;"{% endif %}>
<div class="has-text-weight-bold tab-nested-div ml-1 mb-3">
EPSS History Table
</div>
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth gray-header-border" id="epss-history-table">
<thead>
<tr>
<th>Published At</th>
<th>EPSS Score</th>
<th>Percentile</th>
</tr>
</thead>
<tbody>
{% for row in epss_history_data reversed %}
<tr>
<td>{{ row.published_at|date:"M d, Y" }}</td>
<td>{{ row.score|default_if_none:"—" }}</td>
<td>{{ row.percentile|default_if_none:"—" }}</td>
</tr>
{% endfor %}
</tbody>
</table>

{% if epss_pagination_obj and epss_pagination_obj.has_other_pages %}
<nav class="pagination is-small is-centered mt-4" role="navigation" aria-label="pagination">
{% if epss_pagination_obj.has_previous %}
<a class="pagination-previous" href="?epss_page={{ epss_pagination_obj.previous_page_number }}">Newer</a>
{% else %}
<a class="pagination-previous" disabled>Newer</a>
{% endif %}

{% if epss_pagination_obj.has_next %}
<a class="pagination-next" href="?epss_page={{ epss_pagination_obj.next_page_number }}">Older</a>
{% else %}
<a class="pagination-next" disabled>Older</a>
{% endif %}
</nav>
{% endif %}
</div>
{% endif %}
{% else %}
<p>No EPSS data available for this advisory.</p>
{% endif %}
Expand Down Expand Up @@ -684,7 +747,7 @@
{% endif %}
</div>

<!-- <div class="tab-div content" data-content="history">
{% comment %} <div class="tab-div content" data-content="history">
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
<thead>
<tr>
Expand Down Expand Up @@ -728,13 +791,21 @@
</tr>
{% endfor %}
</table>
</div> -->
</div> {% endcomment %}
</div>
</div>
</section>
{% endif %}

<script src="{% static 'js/main.js' %}" crossorigin="anonymous"></script>
<script src="{% static 'js/main.js' %}"></script>

{% if 'epss_page' in request.GET or severities %}
<link rel="stylesheet" href="{% static 'css/billboard.css' %}">
<script src="{% static 'js/d3.js' %}"></script>
<script src="{% static 'js/billboard.js' %}"></script>
{% endif %}

{{ epss_history_data|json_script:"epss-history-data" }}

<script>
function goToTab(tabName) {
Expand All @@ -752,4 +823,6 @@
}
</script>

<script src="{% static 'js/advisory_detail.js' %}"></script>

{% endblock %}
152 changes: 152 additions & 0 deletions vulnerabilities/tests/test_data/epss/epss_history_expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
[
{
"score": 0.00048,
"percentile": 0.14616,
"published_at": "2026-05-02"
},
{
"score": 0.00048,
"percentile": 0.14593,
"published_at": "2026-05-03"
},
{
"score": 0.00048,
"percentile": 0.1453,
"published_at": "2026-05-04"
},
{
"score": 0.00048,
"percentile": 0.1453,
"published_at": "2026-05-05"
},
{
"score": 0.00048,
"percentile": 0.1453,
"published_at": "2026-05-06"
},
{
"score": 0.00048,
"percentile": 0.14663,
"published_at": "2026-05-07"
},
{
"score": 0.00048,
"percentile": 0.14697,
"published_at": "2026-05-08"
},
{
"score": 0.00048,
"percentile": 0.14752,
"published_at": "2026-05-09"
},
{
"score": 0.00048,
"percentile": 0.14765,
"published_at": "2026-05-10"
},
{
"score": 0.00048,
"percentile": 0.14748,
"published_at": "2026-05-11"
},
{
"score": 0.00048,
"percentile": 0.14793,
"published_at": "2026-05-12"
},
{
"score": 0.00048,
"percentile": 0.14815,
"published_at": "2026-05-13"
},
{
"score": 0.00048,
"percentile": 0.14874,
"published_at": "2026-05-14"
},
{
"score": 0.00048,
"percentile": 0.14881,
"published_at": "2026-05-15"
},
{
"score": 0.00048,
"percentile": 0.14905,
"published_at": "2026-05-16"
},
{
"score": 0.00048,
"percentile": 0.14886,
"published_at": "2026-05-17"
},
{
"score": 0.00048,
"percentile": 0.14837,
"published_at": "2026-05-18"
},
{
"score": 0.00048,
"percentile": 0.14816,
"published_at": "2026-05-19"
},
{
"score": 0.00048,
"percentile": 0.14827,
"published_at": "2026-05-20"
},
{
"score": 0.00048,
"percentile": 0.14803,
"published_at": "2026-05-21"
},
{
"score": 0.00048,
"percentile": 0.14978,
"published_at": "2026-05-22"
},
{
"score": 0.00048,
"percentile": 0.14966,
"published_at": "2026-05-23"
},
{
"score": 0.00048,
"percentile": 0.14918,
"published_at": "2026-05-24"
},
{
"score": 0.00048,
"percentile": 0.14902,
"published_at": "2026-05-25"
},
{
"score": 0.00048,
"percentile": 0.14898,
"published_at": "2026-05-26"
},
{
"score": 0.00048,
"percentile": 0.14998,
"published_at": "2026-05-27"
},
{
"score": 0.00048,
"percentile": 0.15143,
"published_at": "2026-05-28"
},
{
"score": 0.00048,
"percentile": 0.15216,
"published_at": "2026-05-29"
},
{
"score": 0.00048,
"percentile": 0.15204,
"published_at": "2026-05-30"
},
{
"score": 0.00048,
"percentile": 0.15171,
"published_at": "2026-05-31"
}
]
Loading