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">

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this change?

<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>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to make this change? Adding crossorigin="anonymous" protects user privacy.

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


{% if 'epss_page' in request.GET or severities %}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to keep the template simple, it would be better to move this lookup into the view and pass a boolean flag to the template

Suggested change
{% if 'epss_page' in request.GET or severities %}
{% if show_epss_chart %}

<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
Loading