mirror of
https://github.com/0xMarcio/cve.git
synced 2026-05-27 06:12:23 +02:00
Fix search layout and add dynamic CVE pages
This commit is contained in:
+1
-6
@@ -1,9 +1,4 @@
|
||||
data/
|
||||
.venv/
|
||||
docs/api/
|
||||
docs/cve/
|
||||
docs/epss/
|
||||
docs/kev/
|
||||
docs/diffs/
|
||||
docs/vendors/
|
||||
docs/api/v1/cve/
|
||||
scripts/__pycache__/
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Redirecting…</title>
|
||||
<meta http-equiv="refresh" content="3;url=/" />
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
</head>
|
||||
<body class="color-no-search">
|
||||
<main class="wrap">
|
||||
<section class="hero">
|
||||
<p class="eyebrow">Not found</p>
|
||||
<h1>Redirecting…</h1>
|
||||
<p class="lede" id="msg">Trying to find the right page.</p>
|
||||
</section>
|
||||
</main>
|
||||
<script>
|
||||
(function() {
|
||||
const path = window.location.pathname;
|
||||
const cveMatch = path.match(/\\/cve\\/((CVE-\\d{4}-\\d+))\\.html/i);
|
||||
if (cveMatch) {
|
||||
const target = `/cve/?id=${cveMatch[1].toUpperCase()}`;
|
||||
document.getElementById('msg').textContent = `Sending you to ${target}`;
|
||||
window.location.replace(target);
|
||||
return;
|
||||
}
|
||||
const navMatch = path.match(/^\\/(kev|epss|diffs)$/i);
|
||||
if (navMatch) {
|
||||
window.location.replace(`/${navMatch[1].toLowerCase()}/`);
|
||||
return;
|
||||
}
|
||||
document.getElementById('msg').textContent = 'Page not found. Taking you home…';
|
||||
setTimeout(() => window.location.replace('/'), 1500);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"generated": "2025-12-17",
|
||||
"items": [
|
||||
{
|
||||
"cve": "CVE-2025-9316",
|
||||
"epss": 0.78706,
|
||||
"percentile": 0.98995,
|
||||
"poc_count": 0,
|
||||
"summary": ""
|
||||
},
|
||||
{
|
||||
"cve": "CVE-2025-8943",
|
||||
"epss": 0.6583,
|
||||
"percentile": 0.9843,
|
||||
"poc_count": 1,
|
||||
"summary": "The Custom MCPs feature is designed to execute OS commands, for instance, using tools like `npx` to spin up local MCP Servers. However, Flowise's inherent authentication and authorization model is minimal and lacks ro..."
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+19294
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,125 @@
|
||||
(function () {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const rawId = params.get("id") || params.get("cve");
|
||||
const cveId = rawId ? rawId.toUpperCase() : null;
|
||||
|
||||
const titleEl = document.getElementById("cve-title");
|
||||
const summaryEl = document.getElementById("cve-summary");
|
||||
const metaEl = document.getElementById("cve-meta");
|
||||
const descEl = document.getElementById("cve-description");
|
||||
const factsEl = document.getElementById("cve-facts");
|
||||
const pocRowsEl = document.getElementById("cve-poc-rows");
|
||||
const kevRowsEl = document.getElementById("kev-rows");
|
||||
|
||||
const detailSection = document.getElementById("cve-details");
|
||||
const notFoundSection = document.getElementById("not-found");
|
||||
|
||||
function setLoading(message) {
|
||||
titleEl.textContent = cveId || "CVE details";
|
||||
summaryEl.textContent = message;
|
||||
}
|
||||
|
||||
function renderFacts(data) {
|
||||
const items = [];
|
||||
if (data.vendor) items.push({ label: "Vendor", value: data.vendor });
|
||||
if (data.product) items.push({ label: "Product", value: data.product });
|
||||
if (data.epss !== undefined && data.epss !== null) items.push({ label: "EPSS", value: data.epss.toFixed(3) });
|
||||
if (data.percentile !== undefined && data.percentile !== null) items.push({ label: "Percentile", value: `${Math.round(data.percentile * 100)}th` });
|
||||
if (data.poc_count !== undefined) items.push({ label: "PoCs", value: data.poc_count });
|
||||
|
||||
factsEl.innerHTML = items
|
||||
.map((item) => `<div class="stat"><strong>${item.value}</strong><span>${item.label}</span></div>`)
|
||||
.join("");
|
||||
}
|
||||
|
||||
function renderPocs(links) {
|
||||
pocRowsEl.innerHTML = "";
|
||||
if (!links || links.length === 0) {
|
||||
pocRowsEl.innerHTML = '<tr><td class="muted">No PoC links available.</td></tr>';
|
||||
return;
|
||||
}
|
||||
pocRowsEl.innerHTML = links
|
||||
.map((link) => `<tr><td><a href="${link}" target="_blank" rel="noreferrer">${link}</a></td></tr>`)
|
||||
.join("");
|
||||
}
|
||||
|
||||
function renderKev(kev) {
|
||||
if (!kev) {
|
||||
document.getElementById("kev-section").style.display = "none";
|
||||
return;
|
||||
}
|
||||
const rows = [];
|
||||
if (kev.short_description) rows.push(["Summary", kev.short_description]);
|
||||
if (kev.date_added) rows.push(["Date added", kev.date_added]);
|
||||
if (kev.due_date) rows.push(["Due", kev.due_date]);
|
||||
if (kev.required_action) rows.push(["Required action", kev.required_action]);
|
||||
if (kev.notes) rows.push(["Notes", kev.notes]);
|
||||
kevRowsEl.innerHTML = rows.map(([k, v]) => `<tr><th>${k}</th><td>${v}</td></tr>`).join("");
|
||||
document.getElementById("kev-section").style.display = "";
|
||||
}
|
||||
|
||||
async function fetchCveFromApi(id) {
|
||||
const res = await fetch(`/api/v1/cve/${id}.json`, { cache: "no-store" });
|
||||
if (!res.ok) throw new Error("notfound");
|
||||
return res.json();
|
||||
}
|
||||
|
||||
async function fetchFromList(id) {
|
||||
const res = await fetch("/CVE_list.json", { cache: "no-store" });
|
||||
if (!res.ok) throw new Error("fallback-missing");
|
||||
const data = await res.json();
|
||||
const match = (data || []).find((row) => (row.cve || "").toUpperCase() === id);
|
||||
if (!match) throw new Error("fallback-notfound");
|
||||
return {
|
||||
cve: id,
|
||||
description: match.desc,
|
||||
poc_links: match.poc || [],
|
||||
poc_count: (match.poc || []).length,
|
||||
};
|
||||
}
|
||||
|
||||
async function load() {
|
||||
if (!cveId) {
|
||||
setLoading("Provide ?id=CVE-YYYY-#### in the URL to view details.");
|
||||
notFoundSection.style.display = "";
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading("Loading CVE details…");
|
||||
try {
|
||||
const data = await fetchCveFromApi(cveId);
|
||||
titleEl.textContent = data.cve || cveId;
|
||||
summaryEl.textContent = data.description || "No description available.";
|
||||
renderFacts(data);
|
||||
renderPocs(data.poc_links || data.poc || []);
|
||||
renderKev(data.kev);
|
||||
detailSection.style.display = "";
|
||||
notFoundSection.style.display = "none";
|
||||
metaEl.innerHTML = `<span class="pill">Vendor: ${data.vendor || "n/a"}</span><span class="pill">Product: ${data.product || "n/a"}</span><span class="pill">PoCs: ${data.poc_count ?? (data.poc_links || []).length}</span>`;
|
||||
return;
|
||||
} catch (err) {
|
||||
console.warn("API lookup failed, trying CVE_list.json", err);
|
||||
}
|
||||
|
||||
try {
|
||||
const fallback = await fetchFromList(cveId);
|
||||
titleEl.textContent = fallback.cve;
|
||||
summaryEl.textContent = fallback.description || "No description available.";
|
||||
renderFacts(fallback);
|
||||
renderPocs(fallback.poc_links || fallback.poc || []);
|
||||
renderKev(null);
|
||||
detailSection.style.display = "";
|
||||
notFoundSection.style.display = "none";
|
||||
metaEl.innerHTML = `<span class="pill">PoCs: ${fallback.poc_count || 0}</span>`;
|
||||
} catch (err) {
|
||||
console.warn("CVE_list lookup failed", err);
|
||||
notFoundSection.style.display = "";
|
||||
detailSection.style.display = "none";
|
||||
metaEl.innerHTML = "";
|
||||
titleEl.textContent = cveId;
|
||||
summaryEl.textContent = "No data found for this CVE.";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", load);
|
||||
})();
|
||||
@@ -0,0 +1,79 @@
|
||||
(function () {
|
||||
function cardTemplate(item) {
|
||||
return `
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/?id=${item.cve}">${item.cve}</a></div>
|
||||
<div class="card-meta">EPSS ${item.epss !== null && item.epss !== undefined ? item.epss.toFixed(3) : "0.000"} • ${item.percentile !== null && item.percentile !== undefined ? Math.round(item.percentile * 100) + "th pct" : ""}</div>
|
||||
<p>${item.summary || "No description."}</p>
|
||||
${item.vendor ? `<div class="badge">${item.vendor}</div>` : ""}
|
||||
${item.product ? `<div class="badge">${item.product}</div>` : ""}
|
||||
</article>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderCards(gridId, items) {
|
||||
const el = document.getElementById(gridId);
|
||||
if (!el) return;
|
||||
if (!items || items.length === 0) {
|
||||
el.innerHTML = '<p class="muted">No data available.</p>';
|
||||
return;
|
||||
}
|
||||
el.innerHTML = items.map(cardTemplate).join("");
|
||||
}
|
||||
|
||||
function renderDiffTable(diff) {
|
||||
const tbody = document.getElementById("diff-table-body");
|
||||
if (!tbody) return;
|
||||
const kevCount = (diff.new_kev_entries || []).length;
|
||||
const kevExamples = (diff.new_kev_entries || []).slice(0, 5).map((row) => `<a href="/cve/?id=${row.cve}">${row.cve}</a>`).join(", ") || "None";
|
||||
|
||||
const epssCount = (diff.new_high_epss || []).length;
|
||||
const epssExamples = (diff.new_high_epss || []).slice(0, 5).map((row) => `<a href="/cve/?id=${row.cve}">${row.cve}</a>`).join(", ") || "None";
|
||||
|
||||
const moverCount = (diff.epss_movers || []).length;
|
||||
const moverExamples = (diff.epss_movers || []).slice(0, 5).map((row) => `<a href="/cve/?id=${row.cve}">${row.cve}</a> (${row.delta.toFixed(3)})`).join(", ") || "None";
|
||||
|
||||
tbody.innerHTML = `
|
||||
<tr>
|
||||
<td>New KEV entries</td>
|
||||
<td>${kevCount}</td>
|
||||
<td>${kevExamples}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>New high EPSS</td>
|
||||
<td>${epssCount}</td>
|
||||
<td>${epssExamples}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Top EPSS movers</td>
|
||||
<td>${moverCount}</td>
|
||||
<td>${moverExamples}</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
async function loadHome() {
|
||||
try {
|
||||
const res = await fetch("/api/v1/joined_top.json", { cache: "no-store" });
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
renderCards("kev-grid", (data.kev_top || []).slice(0, 15));
|
||||
renderCards("epss-grid", (data.high_epss || []).slice(0, 15));
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("Failed to load joined_top.json", err);
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch("/api/v1/diff/latest.json", { cache: "no-store" });
|
||||
if (res.ok) {
|
||||
const diff = await res.json();
|
||||
renderDiffTable(diff);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("Failed to load diff", err);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", loadHome);
|
||||
})();
|
||||
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>CVE Details - CVE PoC Hub</title>
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
<script defer src="/assets/cve.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<div class="wrap">
|
||||
<div class="brand"><a href="/">CVE PoC Hub</a><span>daily</span></div>
|
||||
<nav>
|
||||
<a href="/search/">PoC Search</a>
|
||||
<a href="/kev/">KEV</a>
|
||||
<a href="/epss/">EPSS</a>
|
||||
<a href="/diffs/">Diffs</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main class="wrap" id="cve-page">
|
||||
<section class="hero">
|
||||
<p class="eyebrow">CVE detail</p>
|
||||
<h1 id="cve-title">Loading…</h1>
|
||||
<p class="lede" id="cve-summary">Fetching CVE data.</p>
|
||||
<div class="pill-row tight" id="cve-meta"></div>
|
||||
<div class="search-meta">
|
||||
<span>Data source: <code>/api/v1/cve/<id>.json</code></span>
|
||||
<span>Fallback: <code>CVE_list.json</code></span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" id="cve-details" style="display:none;">
|
||||
<h2>Description</h2>
|
||||
<p id="cve-description" class="muted"></p>
|
||||
|
||||
<div class="subtle-grid" id="cve-facts"></div>
|
||||
|
||||
<h2>PoC Links</h2>
|
||||
<div id="cve-pocs" class="table-responsive">
|
||||
<table class="list">
|
||||
<thead><tr><th>Link</th></tr></thead>
|
||||
<tbody id="cve-poc-rows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="kev-section" style="display:none;">
|
||||
<h2>KEV details</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="list">
|
||||
<tbody id="kev-rows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" id="not-found" style="display:none;">
|
||||
<h2>Not found</h2>
|
||||
<p class="muted">We could not find this CVE in the API or CVE_list.json. Check the identifier and try again.</p>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="wrap">
|
||||
<span>Data via GitHub Actions + Trickest feed</span>
|
||||
<span><a href="https://github.com/0xMarcio/cve">GitHub repo</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,117 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Diffs - CVE PoC Hub</title>
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<div class="wrap">
|
||||
<div class="brand"><a href="/">CVE PoC Hub</a><span>daily</span></div>
|
||||
<nav>
|
||||
<a href="/search/">PoC Search</a>
|
||||
<a href="/kev/">KEV</a>
|
||||
<a href="/epss/">EPSS</a>
|
||||
<a href="/diffs/">Diffs</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main class="wrap">
|
||||
<section class="section">
|
||||
<h1>Daily Diff</h1>
|
||||
<p class="muted">Newest changes from <code>/api/v1/diff/latest.json</code>.</p>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>New KEV Entries</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="list">
|
||||
<thead><tr><th>CVE</th><th>Vendor</th><th>Product</th><th>Date Added</th></tr></thead>
|
||||
<tbody id="diff-kev"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>New High EPSS</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="list">
|
||||
<thead><tr><th>CVE</th><th>EPSS</th><th>Percentile</th></tr></thead>
|
||||
<tbody id="diff-epss"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Biggest EPSS Movers</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="list">
|
||||
<thead><tr><th>CVE</th><th>Δ EPSS</th><th>Current</th></tr></thead>
|
||||
<tbody id="diff-movers"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="wrap">
|
||||
<span>Data: CISA KEV, FIRST EPSS, community PoCs</span>
|
||||
<span><a href="https://github.com/0xMarcio/cve">GitHub repo</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
function renderRows(target, rows, columns, emptyText) {
|
||||
const el = document.getElementById(target);
|
||||
if (!rows || rows.length === 0) {
|
||||
el.innerHTML = `<tr><td colspan="${columns}" class="muted">${emptyText}</td></tr>`;
|
||||
return;
|
||||
}
|
||||
el.innerHTML = rows.join("");
|
||||
}
|
||||
|
||||
async function loadDiff() {
|
||||
try {
|
||||
const res = await fetch("/api/v1/diff/latest.json", { cache: "no-store" });
|
||||
if (!res.ok) throw new Error("Failed to load diff");
|
||||
const data = await res.json();
|
||||
|
||||
const kevRows = (data.new_kev_entries || []).map(row => `
|
||||
<tr>
|
||||
<td><a href="/cve/?id=${row.cve}">${row.cve}</a></td>
|
||||
<td>${row.vendor || ""}</td>
|
||||
<td>${row.product || ""}</td>
|
||||
<td>${row.date_added || ""}</td>
|
||||
</tr>
|
||||
`);
|
||||
renderRows("diff-kev", kevRows, 4, "No new KEV entries.");
|
||||
|
||||
const epssRows = (data.new_high_epss || []).map(row => `
|
||||
<tr>
|
||||
<td><a href="/cve/?id=${row.cve}">${row.cve}</a></td>
|
||||
<td>${row.epss !== null && row.epss !== undefined ? row.epss.toFixed(3) : ""}</td>
|
||||
<td>${row.percentile !== null && row.percentile !== undefined ? Math.round(row.percentile * 100) + "th" : ""}</td>
|
||||
</tr>
|
||||
`);
|
||||
renderRows("diff-epss", epssRows, 3, "No new high EPSS items.");
|
||||
|
||||
const moverRows = (data.epss_movers || []).map(row => `
|
||||
<tr>
|
||||
<td><a href="/cve/?id=${row.cve}">${row.cve}</a></td>
|
||||
<td>${row.delta !== undefined ? row.delta.toFixed(3) : ""}</td>
|
||||
<td>${row.epss !== undefined ? row.epss.toFixed(3) : ""}</td>
|
||||
</tr>
|
||||
`);
|
||||
renderRows("diff-movers", moverRows, 3, "No movers yet.");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
renderRows("diff-kev", [], 4, "Unable to load diff data.");
|
||||
renderRows("diff-epss", [], 3, "Unable to load diff data.");
|
||||
renderRows("diff-movers", [], 3, "Unable to load diff data.");
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", loadDiff);
|
||||
</script>
|
||||
<script defer src="/assets/site.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>EPSS - CVE PoC Hub</title>
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<div class="wrap">
|
||||
<div class="brand"><a href="/">CVE PoC Hub</a><span>daily</span></div>
|
||||
<nav>
|
||||
<a href="/search/">PoC Search</a>
|
||||
<a href="/kev/">KEV</a>
|
||||
<a href="/epss/">EPSS</a>
|
||||
<a href="/diffs/">Diffs</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main class="wrap">
|
||||
<section class="section">
|
||||
<h1>EPSS highlights</h1>
|
||||
<p class="muted">High-probability EPSS picks that are not in KEV. Data from <code>/api/v1/epss_top.json</code>.</p>
|
||||
<input type="search" placeholder="Filter CVE" data-filter-table="epss-table" class="filter" />
|
||||
<div class="table-responsive">
|
||||
<table class="list" id="epss-table">
|
||||
<thead><tr><th>CVE</th><th>EPSS</th><th>Percentile</th><th>PoCs</th><th>Description</th></tr></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="wrap">
|
||||
<span>Data: CISA KEV, FIRST EPSS, community PoCs</span>
|
||||
<span><a href="https://github.com/0xMarcio/cve">GitHub repo</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
async function loadEpss() {
|
||||
const tbody = document.querySelector("#epss-table tbody");
|
||||
try {
|
||||
const res = await fetch("/api/v1/epss_top.json", { cache: "no-store" });
|
||||
if (!res.ok) throw new Error("Failed to load EPSS");
|
||||
const data = await res.json();
|
||||
const items = data.items || [];
|
||||
tbody.innerHTML = items.map(row => `
|
||||
<tr>
|
||||
<td><a href="/cve/?id=${row.cve}">${row.cve}</a></td>
|
||||
<td>${row.epss !== null && row.epss !== undefined ? row.epss.toFixed(3) : ""}</td>
|
||||
<td>${row.percentile !== null && row.percentile !== undefined ? Math.round(row.percentile * 100) + "th" : ""}</td>
|
||||
<td>${row.poc_count || 0}</td>
|
||||
<td>${row.summary || ""}</td>
|
||||
</tr>
|
||||
`).join("");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="muted">Unable to load EPSS data.</td></tr>';
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", loadEpss);
|
||||
</script>
|
||||
<script defer src="/assets/site.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+25
-24
@@ -6,6 +6,7 @@
|
||||
<title>CVE PoC Hub</title>
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
<script defer src="/assets/site.js"></script>
|
||||
<script defer src="/assets/home.js"></script>
|
||||
</head>
|
||||
<body class="color-no-search">
|
||||
<header class="site-header">
|
||||
@@ -65,107 +66,107 @@
|
||||
<section class="section">
|
||||
<h1>KEV with high EPSS</h1>
|
||||
<p class="muted">KEV items that also carry high EPSS probability.</p>
|
||||
<div class="card-grid">
|
||||
<div class="card-grid" id="kev-grid">
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-9242.html">CVE-2025-9242</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-9242">CVE-2025-9242</a></div>
|
||||
<div class="card-meta">EPSS 0.744 • 99th pct</div>
|
||||
<p>No description.</p>
|
||||
<div class="badge">WatchGuard</div>
|
||||
<div class="badge">Firebox</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-7775.html">CVE-2025-7775</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-7775">CVE-2025-7775</a></div>
|
||||
<div class="card-meta">EPSS 0.174 • 95th pct</div>
|
||||
<p>Memory overflow vulnerability leading to Remote Code Execution and/or Denial of Service in NetScaler ADC and NetScaler Gateway when NetScaler is configured as Gateway (VPN virtual server, ICA Proxy, CVPN, RDP Proxy) o...</p>
|
||||
<div class="badge">Citrix</div>
|
||||
<div class="badge">NetScaler</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-9377.html">CVE-2025-9377</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-9377">CVE-2025-9377</a></div>
|
||||
<div class="card-meta">EPSS 0.146 • 94th pct</div>
|
||||
<p>The authenticated remote command execution (RCE) vulnerability exists in the Parental Control page on TP-Link Archer C7(EU) V2 and TL-WR841N/ND(MS) V9.This issue affects Archer C7(EU) V2: before 241108 and TL-WR841N/N...</p>
|
||||
<div class="badge">TP-Link</div>
|
||||
<div class="badge">Multiple Routers</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-8876.html">CVE-2025-8876</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-8876">CVE-2025-8876</a></div>
|
||||
<div class="card-meta">EPSS 0.139 • 94th pct</div>
|
||||
<p>Improper Input Validation vulnerability in N-able N-central allows OS Command Injection.This issue affects N-central: before 2025.3.1.</p>
|
||||
<div class="badge">N-able</div>
|
||||
<div class="badge">N-Central</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-8875.html">CVE-2025-8875</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-8875">CVE-2025-8875</a></div>
|
||||
<div class="card-meta">EPSS 0.051 • 89th pct</div>
|
||||
<p>Deserialization of Untrusted Data vulnerability in N-able N-central allows Local Execution of Code.This issue affects N-central: before 2025.3.1.</p>
|
||||
<div class="badge">N-able</div>
|
||||
<div class="badge">N-Central</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-8088.html">CVE-2025-8088</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-8088">CVE-2025-8088</a></div>
|
||||
<div class="card-meta">EPSS 0.032 • 86th pct</div>
|
||||
<p>A path traversal vulnerability affecting the Windows version of WinRAR allows the attackers to execute arbitrary code by crafting malicious archive files. This vulnerability was exploited in the wild and was discovere...</p>
|
||||
<div class="badge">RARLAB</div>
|
||||
<div class="badge">WinRAR</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2002-0367.html">CVE-2002-0367</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2002-0367">CVE-2002-0367</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>smss.exe debugging subsystem in Windows NT and Windows 2000 does not properly authenticate programs that connect to other programs, which allows local users to gain administrator or SYSTEM privileges by duplicating a...</p>
|
||||
<div class="badge">Microsoft</div>
|
||||
<div class="badge">Windows</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2004-0210.html">CVE-2004-0210</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2004-0210">CVE-2004-0210</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>The POSIX component of Microsoft Windows NT and Windows 2000 allows local users to execute arbitrary code via certain parameters, possibly by modifying message length values and causing a buffer overflow.</p>
|
||||
<div class="badge">Microsoft</div>
|
||||
<div class="badge">Windows</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2004-1464.html">CVE-2004-1464</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2004-1464">CVE-2004-1464</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>Cisco IOS 12.2(15) and earlier allows remote attackers to cause a denial of service (refused VTY (virtual terminal) connections), via a crafted TCP connection to the Telnet or reverse Telnet port.</p>
|
||||
<div class="badge">Cisco</div>
|
||||
<div class="badge">IOS</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2005-2773.html">CVE-2005-2773</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2005-2773">CVE-2005-2773</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>HP OpenView Network Node Manager 6.2 through 7.50 allows remote attackers to execute arbitrary commands via shell metacharacters in the (1) node parameter to connectedNodes.ovpl, (2) cdpView.ovpl, (3) freeIPaddrs.ovpl...</p>
|
||||
<div class="badge">Hewlett Packard (HP)</div>
|
||||
<div class="badge">OpenView Network Node Manager</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2006-1547.html">CVE-2006-1547</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2006-1547">CVE-2006-1547</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>ActionForm in Apache Software Foundation (ASF) Struts before 1.2.9 with BeanUtils 1.7 allows remote attackers to cause a denial of service via a multipart/form-data encoded form with a parameter name that references t...</p>
|
||||
<div class="badge">Apache</div>
|
||||
<div class="badge">Struts 1</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2006-2492.html">CVE-2006-2492</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2006-2492">CVE-2006-2492</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>Buffer overflow in Microsoft Word in Office 2000 SP3, Office XP SP3, Office 2003 Sp1 and SP2, and Microsoft Works Suites through 2006, allows user-assisted attackers to execute arbitrary code via a malformed object po...</p>
|
||||
<div class="badge">Microsoft</div>
|
||||
<div class="badge">Word</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2007-0671.html">CVE-2007-0671</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2007-0671">CVE-2007-0671</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>Unspecified vulnerability in Microsoft Excel 2000, XP, 2003, and 2004 for Mac, and possibly other Office products, allows remote user-assisted attackers to execute arbitrary code via unknown attack vectors, as demonst...</p>
|
||||
<div class="badge">Microsoft</div>
|
||||
<div class="badge">Office</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2007-3010.html">CVE-2007-3010</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2007-3010">CVE-2007-3010</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>masterCGI in the Unified Maintenance Tool in Alcatel OmniPCX Enterprise Communication Server R7.1 and earlier allows remote attackers to execute arbitrary commands via shell metacharacters in the user parameter during...</p>
|
||||
<div class="badge">Alcatel</div>
|
||||
<div class="badge">OmniPCX Enterprise</div>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2007-5659.html">CVE-2007-5659</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2007-5659">CVE-2007-5659</a></div>
|
||||
<div class="card-meta">EPSS 0.000 • 0th pct</div>
|
||||
<p>Multiple buffer overflows in Adobe Reader and Acrobat 8.1.1 and earlier allow remote attackers to execute arbitrary code via a PDF file with long arguments to unspecified JavaScript methods. NOTE: this issue might be...</p>
|
||||
<div class="badge">Adobe</div>
|
||||
@@ -177,14 +178,14 @@
|
||||
<section class="section">
|
||||
<h1>EPSS picks not in KEV</h1>
|
||||
<p class="muted">High-probability EPSS items that are not yet in the KEV list.</p>
|
||||
<div class="card-grid">
|
||||
<div class="card-grid" id="epss-grid">
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-9316.html">CVE-2025-9316</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-9316">CVE-2025-9316</a></div>
|
||||
<div class="card-meta">EPSS 0.787 • 99th pct</div>
|
||||
<p>No description.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/CVE-2025-8943.html">CVE-2025-8943</a></div>
|
||||
<div class="card-title"><a href="/cve/?id=CVE-2025-8943">CVE-2025-8943</a></div>
|
||||
<div class="card-meta">EPSS 0.658 • 98th pct</div>
|
||||
<p>The Custom MCPs feature is designed to execute OS commands, for instance, using tools like `npx` to spin up local MCP Servers. However, Flowise's inherent authentication and authorization model is minimal and lacks ro...</p>
|
||||
</article>
|
||||
@@ -195,7 +196,7 @@
|
||||
<h1>Trending PoCs</h1>
|
||||
<p class="muted">Fresh GitHub PoCs by stars and recency.</p>
|
||||
<div class="table-responsive">
|
||||
<table class="list">
|
||||
<table class="list" id="trending-table">
|
||||
<thead><tr><th>Stars</th><th>Updated</th><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
@@ -329,18 +330,18 @@
|
||||
<div class="table-responsive">
|
||||
<table class="list">
|
||||
<thead><tr><th>Type</th><th>Count</th><th>Examples</th></tr></thead>
|
||||
<tbody>
|
||||
<tbody id="diff-table-body">
|
||||
<tr>
|
||||
<td>New KEV entries</td>
|
||||
<td>75</td>
|
||||
<td>
|
||||
<a href="/cve/CVE-2025-9242.html">CVE-2025-9242</a>, <a href="/cve/CVE-2025-7775.html">CVE-2025-7775</a>, <a href="/cve/CVE-2025-9377.html">CVE-2025-9377</a>, <a href="/cve/CVE-2025-8876.html">CVE-2025-8876</a>, <a href="/cve/CVE-2025-8875.html">CVE-2025-8875</a> </td>
|
||||
<a href="/cve/?id=CVE-2025-9242">CVE-2025-9242</a>, <a href="/cve/?id=CVE-2025-7775">CVE-2025-7775</a>, <a href="/cve/?id=CVE-2025-9377">CVE-2025-9377</a>, <a href="/cve/?id=CVE-2025-8876">CVE-2025-8876</a>, <a href="/cve/?id=CVE-2025-8875">CVE-2025-8875</a> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>New high EPSS</td>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<a href="/cve/CVE-2025-9316.html">CVE-2025-9316</a>, <a href="/cve/CVE-2025-8943.html">CVE-2025-8943</a> </td>
|
||||
<a href="/cve/?id=CVE-2025-9316">CVE-2025-9316</a>, <a href="/cve/?id=CVE-2025-8943">CVE-2025-8943</a> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Top EPSS movers</td>
|
||||
@@ -362,4 +363,4 @@ None </td>
|
||||
</footer>
|
||||
<script src="/logic.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>KEV - CVE PoC Hub</title>
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<div class="wrap">
|
||||
<div class="brand"><a href="/">CVE PoC Hub</a><span>daily</span></div>
|
||||
<nav>
|
||||
<a href="/search/">PoC Search</a>
|
||||
<a href="/kev/">KEV</a>
|
||||
<a href="/epss/">EPSS</a>
|
||||
<a href="/diffs/">Diffs</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main class="wrap">
|
||||
<section class="section">
|
||||
<h1>Known Exploited Vulnerabilities</h1>
|
||||
<p class="muted">Live data from <code>/api/v1/kev.json</code>. Filter by CVE, vendor, or product.</p>
|
||||
<input type="search" placeholder="Filter CVE, vendor, product" data-filter-table="kev-table" class="filter" />
|
||||
<div class="table-responsive">
|
||||
<table class="list" id="kev-table">
|
||||
<thead>
|
||||
<tr><th>CVE</th><th>Vendor</th><th>Product</th><th>EPSS</th><th>Percentile</th><th>Date Added</th><th>Due</th></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="wrap">
|
||||
<span>Data: CISA KEV, FIRST EPSS, community PoCs</span>
|
||||
<span><a href="https://github.com/0xMarcio/cve">GitHub repo</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
async function loadKev() {
|
||||
const tbody = document.querySelector("#kev-table tbody");
|
||||
try {
|
||||
const res = await fetch("/api/v1/kev.json", { cache: "no-store" });
|
||||
if (!res.ok) throw new Error("Failed to load KEV");
|
||||
const data = await res.json();
|
||||
const items = data.items || [];
|
||||
tbody.innerHTML = items.map(row => `
|
||||
<tr>
|
||||
<td><a href="/cve/?id=${row.cve}">${row.cve}</a></td>
|
||||
<td>${row.vendor || ""}</td>
|
||||
<td>${row.product || ""}</td>
|
||||
<td>${row.epss !== null && row.epss !== undefined ? row.epss.toFixed(3) : ""}</td>
|
||||
<td>${row.percentile !== null && row.percentile !== undefined ? Math.round(row.percentile * 100) + "th" : ""}</td>
|
||||
<td>${row.date_added || ""}</td>
|
||||
<td>${row.due_date || ""}</td>
|
||||
</tr>
|
||||
`).join("");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
tbody.innerHTML = '<tr><td colspan="7" class="muted">Unable to load KEV data.</td></tr>';
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", loadKev);
|
||||
</script>
|
||||
<script defer src="/assets/site.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+1
-1
@@ -51,7 +51,7 @@ function toggleDropdown(button) {
|
||||
window.toggleDropdown = toggleDropdown;
|
||||
|
||||
function getCveLink(cveId) {
|
||||
return `<a target="_blank" href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=${cveId}"><b>${cveId}</b></a>`;
|
||||
return `<a href="/cve/?id=${cveId}"><b>${cveId}</b></a>`;
|
||||
}
|
||||
|
||||
const controls = {
|
||||
|
||||
+8
-2
@@ -195,6 +195,7 @@ main { padding-top: 1.5rem; }
|
||||
.search-results table.results {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
}
|
||||
.search-results table.results thead td {
|
||||
font-weight: 700;
|
||||
@@ -211,15 +212,20 @@ main { padding-top: 1.5rem; }
|
||||
padding: 0.9rem 1rem;
|
||||
vertical-align: top;
|
||||
color: var(--text);
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.search-results table.results td.desc {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.95rem;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.cveNum { font-weight: 700; font-size: 1.05rem; }
|
||||
.cveNum { font-weight: 700; font-size: 1.05rem; white-space: nowrap; }
|
||||
.poc-container { margin-top: 0.4rem; }
|
||||
.poc-container ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.3rem; }
|
||||
.poc-container li a { word-break: break-all; color: var(--accent); }
|
||||
.poc-container li a { word-break: break-word; overflow-wrap: anywhere; color: var(--accent); }
|
||||
.dropdown-btn {
|
||||
margin-top: 0.4rem;
|
||||
background: transparent;
|
||||
|
||||
+29
-19
@@ -55,38 +55,46 @@ def write_snapshot(joined: Dict) -> Path:
|
||||
return snapshot_path
|
||||
|
||||
|
||||
def build_pages(env: Environment, data: Dict, diff: Dict | None = None) -> None:
|
||||
def build_pages(env: Environment, data: Dict, diff: Dict | None = None, html_mode: str = "summary") -> None:
|
||||
joined = data["joined"]
|
||||
details = data["details"]
|
||||
vendors = data["vendors"]
|
||||
trending = parse_trending_from_readme(README_PATH)
|
||||
|
||||
common_ctx = {"generated": joined["generated"]}
|
||||
render(
|
||||
env,
|
||||
"index.html",
|
||||
{**common_ctx, "data": joined, "trending": trending, "diff": diff or {}},
|
||||
DOCS_DIR / "index.html",
|
||||
)
|
||||
render(env, "kev.html", {**common_ctx, "kev": data["kev_enriched"]}, DOCS_DIR / "kev" / "index.html")
|
||||
render(env, "epss.html", {**common_ctx, "epss": joined["high_epss"]}, DOCS_DIR / "epss" / "index.html")
|
||||
render(env, "diffs.html", {**common_ctx, "diff": diff or {}}, DOCS_DIR / "diffs" / "index.html")
|
||||
if html_mode in {"summary", "all"}:
|
||||
common_ctx = {"generated": joined["generated"]}
|
||||
render(
|
||||
env,
|
||||
"index.html",
|
||||
{**common_ctx, "data": joined, "trending": trending, "diff": diff or {}},
|
||||
DOCS_DIR / "index.html",
|
||||
)
|
||||
render(env, "kev.html", {**common_ctx, "kev": data["kev_enriched"]}, DOCS_DIR / "kev" / "index.html")
|
||||
render(env, "epss.html", {**common_ctx, "epss": joined["high_epss"]}, DOCS_DIR / "epss" / "index.html")
|
||||
render(env, "diffs.html", {**common_ctx, "diff": diff or {}}, DOCS_DIR / "diffs" / "index.html")
|
||||
|
||||
for cve, detail in details.items():
|
||||
render(env, "cve.html", {**common_ctx, "cve": detail}, DOCS_DIR / "cve" / f"{cve}.html")
|
||||
if html_mode == "all":
|
||||
common_ctx = {"generated": joined["generated"]}
|
||||
for cve, detail in details.items():
|
||||
render(env, "cve.html", {**common_ctx, "cve": detail}, DOCS_DIR / "cve" / f"{cve}.html")
|
||||
|
||||
for slug, vendor in vendors.items():
|
||||
cve_details = [details[cve] for cve in vendor["cves"] if cve in details]
|
||||
render(env, "vendor.html", {**common_ctx, "vendor": vendor, "cves": cve_details}, DOCS_DIR / "vendors" / f"{slug}.html")
|
||||
for slug, vendor in vendors.items():
|
||||
cve_details = [details[cve] for cve in vendor["cves"] if cve in details]
|
||||
render(env, "vendor.html", {**common_ctx, "vendor": vendor, "cves": cve_details}, DOCS_DIR / "vendors" / f"{slug}.html")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Build static site and JSON")
|
||||
parser.add_argument(
|
||||
"--html-mode",
|
||||
choices=["none", "summary", "all"],
|
||||
default="none",
|
||||
help="Render no HTML, summary pages only, or all pages including per-CVE.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
ensure_dirs(DOCS_DIR, DOCS_DIR / "cve", DOCS_DIR / "vendors", DOCS_DIR / "kev", DOCS_DIR / "epss", DOCS_DIR / "diffs")
|
||||
ensure_dirs(DOCS_DIR, DOCS_DIR / "kev", DOCS_DIR / "epss", DOCS_DIR / "diffs")
|
||||
|
||||
env = build_env()
|
||||
data = load_joined()
|
||||
# snapshot + diff before rendering so dashboard can show it
|
||||
snapshot_path = write_snapshot(data["joined"])
|
||||
@@ -94,7 +102,9 @@ def main() -> int:
|
||||
diff, target = build_diff(snapshots, threshold=0.5, max_movers=50)
|
||||
prune_snapshots(snapshots, lookback_days=14)
|
||||
|
||||
build_pages(env, data, diff)
|
||||
if args.html_mode != "none":
|
||||
env = build_env()
|
||||
build_pages(env, data, diff, html_mode=args.html_mode)
|
||||
|
||||
# build daily diff after snapshot is written
|
||||
print("Site generated under docs/")
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<tbody>
|
||||
{% for row in diff.new_kev_entries or [] %}
|
||||
<tr>
|
||||
<td><a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a></td>
|
||||
<td><a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a></td>
|
||||
<td>{{ row.vendor }}</td>
|
||||
<td>{{ row.product }}</td>
|
||||
<td>{{ row.date_added }}</td>
|
||||
@@ -32,7 +32,7 @@
|
||||
<tbody>
|
||||
{% for row in diff.new_high_epss or [] %}
|
||||
<tr>
|
||||
<td><a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a></td>
|
||||
<td><a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a></td>
|
||||
<td>{{ '%.3f'|format(row.epss or 0) }}</td>
|
||||
<td>{{ '%2.0f'|format((row.percentile or 0)*100) }}th</td>
|
||||
</tr>
|
||||
@@ -50,7 +50,7 @@
|
||||
<tbody>
|
||||
{% for row in diff.epss_movers or [] %}
|
||||
<tr>
|
||||
<td><a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a></td>
|
||||
<td><a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a></td>
|
||||
<td>{{ '%.3f'|format(row.delta) }}</td>
|
||||
<td>{{ '%.3f'|format(row.epss or 0) }}</td>
|
||||
</tr>
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
<tbody>
|
||||
{% for row in epss %}
|
||||
<tr>
|
||||
<td><a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a></td>
|
||||
<td><a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a></td>
|
||||
<td>{{ '%.3f'|format(row.epss or 0) }}</td>
|
||||
<td>{{ '%2.0f'|format((row.percentile or 0)*100) }}th</td>
|
||||
<td>{{ row.poc_count }}</td>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<div class="card-grid">
|
||||
{% for item in data.kev_top[:15] %}
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/{{ item.cve }}.html">{{ item.cve }}</a></div>
|
||||
<div class="card-title"><a href="/cve/?id={{ item.cve }}">{{ item.cve }}</a></div>
|
||||
<div class="card-meta">EPSS {{ '%.3f'|format(item.epss or 0) }} • {{ '%2.0f'|format((item.percentile or 0)*100) }}th pct</div>
|
||||
<p>{{ item.summary or 'No description.' }}</p>
|
||||
<div class="badge">{{ item.vendor or 'Unknown vendor' }}</div>
|
||||
@@ -65,7 +65,7 @@
|
||||
<div class="card-grid">
|
||||
{% for item in data.high_epss[:15] %}
|
||||
<article class="card">
|
||||
<div class="card-title"><a href="/cve/{{ item.cve }}.html">{{ item.cve }}</a></div>
|
||||
<div class="card-title"><a href="/cve/?id={{ item.cve }}">{{ item.cve }}</a></div>
|
||||
<div class="card-meta">EPSS {{ '%.3f'|format(item.epss or 0) }} • {{ '%2.0f'|format((item.percentile or 0)*100) }}th pct</div>
|
||||
<p>{{ item.summary or 'No description.' }}</p>
|
||||
</article>
|
||||
@@ -105,7 +105,7 @@
|
||||
<td>{{ (diff.new_kev_entries or [])|length }}</td>
|
||||
<td>
|
||||
{% for row in (diff.new_kev_entries or [])[:5] %}
|
||||
<a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a>{% if not loop.last %}, {% endif %}
|
||||
<a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a>{% if not loop.last %}, {% endif %}
|
||||
{% else %}None{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -114,7 +114,7 @@
|
||||
<td>{{ (diff.new_high_epss or [])|length }}</td>
|
||||
<td>
|
||||
{% for row in (diff.new_high_epss or [])[:5] %}
|
||||
<a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a>{% if not loop.last %}, {% endif %}
|
||||
<a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a>{% if not loop.last %}, {% endif %}
|
||||
{% else %}None{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -123,7 +123,7 @@
|
||||
<td>{{ (diff.epss_movers or [])|length }}</td>
|
||||
<td>
|
||||
{% for row in (diff.epss_movers or [])[:5] %}
|
||||
<a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a> ({{ '%.3f'|format(row.delta) }}){% if not loop.last %}, {% endif %}
|
||||
<a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a> ({{ '%.3f'|format(row.delta) }}){% if not loop.last %}, {% endif %}
|
||||
{% else %}None{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
<tbody>
|
||||
{% for row in kev %}
|
||||
<tr>
|
||||
<td><a href="/cve/{{ row.cve }}.html">{{ row.cve }}</a></td>
|
||||
<td><a href="/cve/?id={{ row.cve }}">{{ row.cve }}</a></td>
|
||||
<td>{{ row.vendor }}</td>
|
||||
<td>{{ row.product }}</td>
|
||||
<td>{{ '%.3f'|format(row.epss or 0) }}</td>
|
||||
|
||||
Reference in New Issue
Block a user