From 31ecb2b9484047d02cec675646ba126e2b513799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bonhomme?= Date: Tue, 12 Nov 2024 14:29:57 +0100 Subject: [PATCH 1/9] chg: [website] Improved list of sightings for a vuln and fixed a small issue in the API. --- website/web/api/v1/sighting.py | 9 ++++- website/web/templates/vuln.html | 70 ++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/website/web/api/v1/sighting.py b/website/web/api/v1/sighting.py index eb640fc..cdb5108 100644 --- a/website/web/api/v1/sighting.py +++ b/website/web/api/v1/sighting.py @@ -22,7 +22,7 @@ from website.validators import validate_json from website.web.api.v1.common import auth_func from website.web.api.v1.common import metada_params_model -from website.web.api.v1.common import user_light_params_model +from website.web.api.v1.common import user_params_model from website.web.api.v1.common import uuid_type from website.web.api.v1.types import ResultType from website.models import Sighting @@ -102,6 +102,10 @@ sighting = sighting_ns.model("Sighting", sighting_params_model) metadata = sighting_ns.model("metadata", metada_params_model) +sighting["author"] = fields.Nested( + sighting_ns.model("User", user_params_model), readonly=True +) + sighting_list_fields = sighting_ns.model( "SightingsList", { @@ -226,7 +230,8 @@ def post(self) -> Tuple[ResultType, int]: ) if ( - Sighting.query.filter( + sighting.get("source", False) + and Sighting.query.filter( Sighting.vulnerability.ilike(sighting["vulnerability"]), Sighting.source == sighting["source"], # func.date(Sighting.creation_timestamp) == func.date(current_time), diff --git a/website/web/templates/vuln.html b/website/web/templates/vuln.html index 0e33db3..10d3bec 100644 --- a/website/web/templates/vuln.html +++ b/website/web/templates/vuln.html @@ -10,6 +10,7 @@ + @@ -261,7 +262,24 @@
Tags
+
+

Sightings

+
+ + + + + + + + + + +
AuthorSourceTypeDate
+
+
+

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • @@ -733,7 +751,7 @@
    Tags
    function loadSightings() { - fetch("{{ url_for('apiv1.sighting_sightings_list', vuln_id=vulnerability_id) }}") + fetch("{{ url_for('apiv1.sighting_sightings_list', vuln_id=vulnerability_id) }}&date_from=1970-01-01") .then(response => response.json()) .then(result => { document.getElementById("nb-sightings").innerText = result.metadata.count; @@ -745,9 +763,56 @@
    Tags
    } else{ drawBarChart(result.data); document.getElementById("sightings-pane-top").style.display = 'block'; - document.getElementById("chart-sightings").innerHTML = "

    Evolution of sightings over time.

    "; + document.getElementById("chart-sightings").innerHTML = "

    Evolution of sightings over time

    "; document.getElementById("sightingsChartContainer").style.display = 'block'; document.getElementById("chart-detailed-legend").style.display = 'block'; + + // clear the table + const tableBody = document.getElementById("sighting-table-body"); + while (tableBody.firstChild) { + tableBody.removeChild(tableBody.firstChild); + } + + result.data + .sort(function (a, b) { + return new Date(b.creation_timestamp) - new Date(a.creation_timestamp); + }) + .map(function (sighting) { + const row = document.createElement('tr'); // Create a table row + + // Create and append the Author cell + const authorCell = document.createElement('td'); + // authorCell.textContent = sighting.author.login; + authorCell.innerHTML = ''+sighting.author.login+''; + row.appendChild(authorCell); + + // Create and append the Source cell + const sourceCell = document.createElement('td'); + // sourceCell.textContent = sighting.source; + sourceCell.innerHTML = ''+sighting.source+''; + row.appendChild(sourceCell); + + // Create and append the Type cell + const typeCell = document.createElement('td'); + typeCell.textContent = sighting.type; + row.appendChild(typeCell); + + // Create and append the Date cell + const dateCell = document.createElement('td'); + dateCell.classList.add('datetime'); + dateCell.textContent = sighting.creation_timestamp; + dateCell.title = sighting.creation_timestamp; + row.appendChild(dateCell); + + document.getElementById("sighting-table-body").appendChild(row); + }) + + var DateTime = luxon.DateTime; + elements = document.getElementsByClassName("datetime"); + Array.prototype.forEach.call(elements, function(element) { + element.textContent = DateTime.fromISO(element.textContent).toRelative() + }); + } }) .catch((error) => { @@ -755,6 +820,7 @@
    Tags
    }); }; + document.getElementById("btnThemeSwitch").addEventListener("click",()=>{ if (document.documentElement.getAttribute("data-bs-theme") == "dark") { Array.from(document.getElementsByClassName("card")).forEach(container => { From f23ba9c8d8296a847f3ec9d22afd0ee805fa4548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bonhomme?= Date: Tue, 12 Nov 2024 14:43:17 +0100 Subject: [PATCH 2/9] chg: [website] display more data in the charts of the home page. --- website/web/static/js/plots.js | 2 +- website/web/templates/search.html | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/website/web/static/js/plots.js b/website/web/static/js/plots.js index baa066f..6bce2b0 100644 --- a/website/web/static/js/plots.js +++ b/website/web/static/js/plots.js @@ -137,7 +137,7 @@ function drawBarChartHomePage(sightings, chartDiv, title, backgroundColor) { // Convert the counts to an array and sort it const sortedVulns = Object.entries(vulnerabilityCounts) .sort(([, a], [, b]) => b - a) - .slice(0, 5); + .slice(0, 8); const labels = sortedVulns.map(([vuln]) => vuln); const dataCounts = sortedVulns.map(([, count]) => count); diff --git a/website/web/templates/search.html b/website/web/templates/search.html index 381ad25..370b805 100644 --- a/website/web/templates/search.html +++ b/website/web/templates/search.html @@ -100,11 +100,11 @@
-
+
{% endif %} @@ -326,19 +326,19 @@
All the vulnerabilites related to {{vendor}} - {{product}}
console.error('Error:', error); }); - fetch("{{ url_for('apiv1.sighting_sightings_list', type='confirmed') }}") - .then(response => response.json()) - .then(result => { - if (result.metadata.count == 0) { - document.getElementById("sightingsChartContainerConfirmed").style.display = 'none'; - } else { - document.getElementById("sightingsChartContainerConfirmed").style.display = 'block'; - drawBarChartHomePage(result.data, 'exploitedVulnsChartConfirmed', 'Confirmed', 'rgba(75, 192, 192, 0.2)'); - } - }) - .catch((error) => { - console.error('Error:', error); - }); + // fetch("{{ url_for('apiv1.sighting_sightings_list', type='confirmed') }}") + // .then(response => response.json()) + // .then(result => { + // if (result.metadata.count == 0) { + // document.getElementById("sightingsChartContainerConfirmed").style.display = 'none'; + // } else { + // document.getElementById("sightingsChartContainerConfirmed").style.display = 'block'; + // drawBarChartHomePage(result.data, 'exploitedVulnsChartConfirmed', 'Confirmed', 'rgba(75, 192, 192, 0.2)'); + // } + // }) + // .catch((error) => { + // console.error('Error:', error); + // }); }; function loadComments() { From 48610fcccd0bbb42bc2ed5c89c00bbfe5ba06184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bonhomme?= Date: Wed, 13 Nov 2024 08:03:07 +0100 Subject: [PATCH 3/9] chg: [website] Added a table of combined sightings for the bundles. Generated in JavaScript on DOMContentLoaded event. --- website/web/templates/bundles/bundle.html | 73 ++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/website/web/templates/bundles/bundle.html b/website/web/templates/bundles/bundle.html index 329caf6..97a307c 100644 --- a/website/web/templates/bundles/bundle.html +++ b/website/web/templates/bundles/bundle.html @@ -48,6 +48,22 @@

Meta

{% endif %}

Author

{{ bundle.author.name }} +
+

Combined sightings

+
+ + + + + + + + + + + +
AuthorVulnerabilitySourceTypeDate
+
+ {% endblock %} @@ -101,7 +102,9 @@

Combined sightings

row.appendChild(typeCell); const dateCell = document.createElement("td"); - dateCell.textContent = new Date(sighting.creation_timestamp).toLocaleString(); + dateCell.classList.add('datetime'); + dateCell.textContent = sighting.creation_timestamp; + dateCell.title = sighting.creation_timestamp; row.appendChild(dateCell); tableBody.appendChild(row); @@ -124,6 +127,14 @@

Combined sightings

// Add each sighting as a row in the table sightingData.data.forEach(sighting => addRowToTable(sighting)); }) + .then(_ => { + var DateTime = luxon.DateTime; + elements = document.getElementsByClassName("datetime"); + Array.prototype.forEach.call(elements, function(element) { + element.textContent = DateTime.fromISO(element.title).toRelative(); + + }); + }) .catch(error => console.error("Error fetching sighting:", error)); }); }) From 8f04be1903c87e79e5c693cae6bb688a14032e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bonhomme?= Date: Wed, 13 Nov 2024 09:28:34 +0100 Subject: [PATCH 5/9] chg: [website] Added a function in order to provide a small description about the vulnerabilities listed in the bundle page. --- website/web/static/js/utils.js | 6 +++ website/web/templates/bundles/bundle.html | 53 ++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/website/web/static/js/utils.js b/website/web/static/js/utils.js index db91b89..c72e256 100644 --- a/website/web/static/js/utils.js +++ b/website/web/static/js/utils.js @@ -71,6 +71,12 @@ function formatMarkdownOutput() { }); } +function truncateString(str, maxLength) { + if (str.length > maxLength) { + return str.slice(0, maxLength) + "..."; + } + return str; +} function findCVEIdentifiers(text) { // Regex pattern to match CVE identifiers (e.g., CVE-2021-34527) diff --git a/website/web/templates/bundles/bundle.html b/website/web/templates/bundles/bundle.html index 4b2fa64..a8f22b9 100644 --- a/website/web/templates/bundles/bundle.html +++ b/website/web/templates/bundles/bundle.html @@ -40,7 +40,7 @@

Description

Vulnerabilities included in this bundle

{% if bundle.meta %} @@ -139,6 +139,8 @@

Combined sightings

}); }) .catch(error => console.error("Error fetching bundle:", error)); + + fetchAndAppendVulnerabilityTitles(); }); function copyCurrentPageURL() { @@ -148,6 +150,55 @@

Combined sightings

}).catch(err => { console.error('Failed to copy: ', err); }); + } + + async function fetchAndAppendVulnerabilityTitles() { + // Select all list items with the class `list-group-item-related` + const listItems = document.querySelectorAll('.list-group-item-related'); + + // Iterate through each list item + for (const listItem of listItems) { + // Get the vulnerability ID from the `vuln-id` attribute + const vulnId = listItem.getAttribute('vuln-id'); + + try { + // Make a GET request to fetch the vulnerability data + const response = await fetch(`/vulnerability/${vulnId}`); + if (!response.ok) throw new Error(`Failed to fetch data for ${vulnId}`); + + // Parse the JSON response + const data = await response.json(); + + // Retrieve the title from the response (CVE) + let description = data?.containers?.cna?.title; + // If description is not found, try to get the English description from descriptions + if (!description) { + const descriptions = data?.containers?.cna?.descriptions || []; + const englishDescription = descriptions.find(desc => desc.lang === "en"); + description = englishDescription ? englishDescription.value : null; + } + // If description still not found, maybe it's GHSA security advisory + if (!description) { + description = data?.details || null; + } + // Final fallback try to find a description in a CSAF security advisory + if (!description) { + description = data?.document?.title || "No description available."; + } + + if (description) { + const span = listItem.querySelector('span') + if (span) { + span.textContent = truncateString(description, 120); + } else { + console.warn(`No span found inside list item for ${vulnId}`); + } + } + } catch (error) { + console.error(`Error fetching data for ${vulnId}:`, error); + } } + } + {% endblock %} From 2fb05648847003918944a77c9ee29beff462e690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bonhomme?= Date: Wed, 13 Nov 2024 09:58:44 +0100 Subject: [PATCH 6/9] chg: [website] Minor change in the comments. --- website/web/templates/bundles/bundle.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/web/templates/bundles/bundle.html b/website/web/templates/bundles/bundle.html index a8f22b9..db11a0a 100644 --- a/website/web/templates/bundles/bundle.html +++ b/website/web/templates/bundles/bundle.html @@ -140,7 +140,7 @@

Combined sightings

}) .catch(error => console.error("Error fetching bundle:", error)); - fetchAndAppendVulnerabilityTitles(); + fetchAndAppendVulnerabilityDescriptions(); }); function copyCurrentPageURL() { @@ -152,7 +152,7 @@

Combined sightings

}); } - async function fetchAndAppendVulnerabilityTitles() { + async function fetchAndAppendVulnerabilityDescriptions() { // Select all list items with the class `list-group-item-related` const listItems = document.querySelectorAll('.list-group-item-related'); @@ -169,7 +169,7 @@

Combined sightings

// Parse the JSON response const data = await response.json(); - // Retrieve the title from the response (CVE) + // Retrieve the title from the response (for CVE) let description = data?.containers?.cna?.title; // If description is not found, try to get the English description from descriptions if (!description) { From 11b9c177a856b5c2f5193724ae83034fa306813f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bonhomme?= Date: Wed, 13 Nov 2024 10:14:03 +0100 Subject: [PATCH 7/9] chg: [website] Make the source link clickable. --- website/web/templates/bundles/bundle.html | 2 +- website/web/templates/search.html | 2 +- website/web/templates/sightings/sightings.html | 12 +++++++++--- website/web/templates/vuln.html | 1 - 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/website/web/templates/bundles/bundle.html b/website/web/templates/bundles/bundle.html index db11a0a..e4fac9c 100644 --- a/website/web/templates/bundles/bundle.html +++ b/website/web/templates/bundles/bundle.html @@ -94,7 +94,7 @@

Combined sightings

row.appendChild(vulnerabilityCell); const sourceCell = document.createElement("td"); - sourceCell.textContent = sighting.source; + sourceCell.innerHTML = ''+sighting.source+''; row.appendChild(sourceCell); const typeCell = document.createElement("td"); diff --git a/website/web/templates/search.html b/website/web/templates/search.html index 370b805..817d814 100644 --- a/website/web/templates/search.html +++ b/website/web/templates/search.html @@ -319,7 +319,7 @@
All the vulnerabilites related to {{vendor}} - {{product}}
document.getElementById("sightingsChartContainerSeen").style.display = 'none'; } else { document.getElementById("sightingsChartContainerSeen").style.display = 'block'; - drawBarChartHomePage(result.data, 'exploitedVulnsChartSeen', 'Mentions dicussions, etc.', 'rgba(75, 192, 75, 0.2)'); + drawBarChartHomePage(result.data, 'exploitedVulnsChartSeen', 'Mentions, dicussions, etc.', 'rgba(75, 192, 75, 0.2)'); } }) .catch((error) => { diff --git a/website/web/templates/sightings/sightings.html b/website/web/templates/sightings/sightings.html index c424d78..50b4f6c 100644 --- a/website/web/templates/sightings/sightings.html +++ b/website/web/templates/sightings/sightings.html @@ -53,9 +53,15 @@

Sightings

-
- {{ pagination.info }} -
+
+ {{ pagination.info }} +
+
+
+
+
+

If a line is highlighted in yellow, it indicates that the vulnerability advisory has not yet been published.

+