From 5c78e585a1d6f980b038c42fb64ac7a6a47cd005 Mon Sep 17 00:00:00 2001 From: 0xMarcio Date: Thu, 18 Dec 2025 07:13:08 +0100 Subject: [PATCH] Simplify site to search + trending --- .github/workflows/build.yml | 69 - .github/workflows/generate_cve_json.yml | 41 - .github/workflows/hot_cves.yml | 2 +- .github/workflows/site.yml | 14 - .github/workflows/static.yml | 45 - docs/404.html | 23 +- docs/assets/app.js | 54 - docs/assets/cve.js | 167 -- docs/assets/home.js | 79 - docs/assets/site.js | 20 - docs/assets/style.css | 97 - docs/cve/index.html | 63 - docs/diffs/index.html | 53 - docs/epss/index.html | 87 - docs/index.html | 283 +-- docs/kev/index.html | 2423 ----------------------- docs/logic.js | 52 +- docs/search/index.html | 66 - docs/trending_poc.json | 4 + scripts/README.md | 2 +- scripts/build_all.py | 6 +- scripts/build_site.py | 313 +-- scripts/site_renderer.py | 99 - templates/base.html | 17 - templates/cve.html | 29 - templates/diffs.html | 27 - templates/epss.html | 26 - templates/index.html | 52 +- templates/kev.html | 30 - templates/pipeline_base.html | 36 - templates/pipeline_cve.html | 46 - templates/pipeline_diff.html | 72 - templates/pipeline_index.html | 69 - templates/pipeline_pocs.html | 47 - templates/vendor.html | 20 - 35 files changed, 286 insertions(+), 4247 deletions(-) delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/generate_cve_json.yml delete mode 100644 .github/workflows/static.yml delete mode 100644 docs/assets/app.js delete mode 100644 docs/assets/cve.js delete mode 100644 docs/assets/home.js delete mode 100644 docs/assets/site.js delete mode 100644 docs/assets/style.css delete mode 100644 docs/cve/index.html delete mode 100644 docs/diffs/index.html delete mode 100644 docs/epss/index.html delete mode 100644 docs/kev/index.html delete mode 100644 docs/search/index.html create mode 100644 docs/trending_poc.json delete mode 100644 scripts/site_renderer.py delete mode 100644 templates/cve.html delete mode 100644 templates/diffs.html delete mode 100644 templates/epss.html delete mode 100644 templates/kev.html delete mode 100644 templates/pipeline_base.html delete mode 100644 templates/pipeline_cve.html delete mode 100644 templates/pipeline_diff.html delete mode 100644 templates/pipeline_index.html delete mode 100644 templates/pipeline_pocs.html delete mode 100644 templates/vendor.html diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index d952b42be2..0000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Build pipeline + Pages - -on: - schedule: - - cron: "15 5 * * *" - workflow_dispatch: - -permissions: - contents: read - pages: write - id-token: write - -concurrency: - group: pages - cancel-in-progress: false - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - - name: Cache dependencies and API cache - uses: actions/cache@v4 - with: - path: | - ~/.cache/pip - data/cache - key: ${{ runner.os }}-cve-pipeline-${{ hashFiles('requirements.txt') }} - restore-keys: | - ${{ runner.os }}-cve-pipeline- - - - name: Install requirements - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Build pipeline outputs + site - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: python scripts/build_all.py --days 7 - - - name: Validate JSON index - run: python -m json.tool docs/api/v1/index.json > /dev/null - - - name: Configure Pages - uses: actions/configure-pages@v5 - - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: docs - - deploy: - needs: build - runs-on: ubuntu-latest - environment: - name: github-pages - url: ${{ steps.deploy.outputs.page_url }} - steps: - - name: Deploy to GitHub Pages - id: deploy - uses: actions/deploy-pages@v4 diff --git a/.github/workflows/generate_cve_json.yml b/.github/workflows/generate_cve_json.yml deleted file mode 100644 index a7feb95c0c..0000000000 --- a/.github/workflows/generate_cve_json.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Generate CVE JSON - -on: - push: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - steps: - - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - - name: Change directory to docs and run CVE JSON generator script - run: | - cd /home/runner/work/cve/cve/docs - python generate_cve_list.py - - - name: Check for changes and commit if necessary - run: | - cd /home/runner/work/cve/cve - git config --global user.name '0xMarcio' - git config --global user.email 'marc@codepwn.win' - git remote set-url origin https://github-actions[bot]:$GITHUB_TOKEN@github.com/0xMarcio/cve.git - - if [ -n "$(git status --porcelain)" ]; then - git add . - git commit -m "Update CVE list $(date +'%Y-%m-%d %H:%M')" - git push origin main - else - echo "No changes to commit" - fi - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/hot_cves.yml b/.github/workflows/hot_cves.yml index f40c2189d6..75b845ff97 100644 --- a/.github/workflows/hot_cves.yml +++ b/.github/workflows/hot_cves.yml @@ -3,7 +3,7 @@ name: Hot CVEs List on: workflow_dispatch: schedule: - - cron: '30 */12 * * *' + - cron: '0 */6 * * *' jobs: ScheduledRun: diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index d10314684b..6c9e03c869 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -7,15 +7,6 @@ on: push: branches: - main - paths: - - 'scripts/**' - - 'templates/**' - - 'docs/assets/**' - - 'README.md' - - '.github/getTrending.py' - - '.github/workflows/hot_cves.yml' - - 'requirements.txt' - - '.github/workflows/site.yml' permissions: contents: read @@ -43,11 +34,6 @@ jobs: python -m pip install --upgrade pip pip install -r requirements.txt - - name: Fetch KEV & EPSS - run: | - python scripts/fetch_kev.py - python scripts/fetch_epss.py - - name: Build site run: python scripts/build_site.py --html-mode summary diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml deleted file mode 100644 index 4198af610f..0000000000 --- a/.github/workflows/static.yml +++ /dev/null @@ -1,45 +0,0 @@ -# Simple workflow for deploying static content to GitHub Pages -name: Deploy cve.codepwn.win - -on: - # Runs on pushes targeting the default branch and changes in the docs directory - push: - branches: ["main"] - paths: - - 'docs/**' - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - # Single deploy job since we're just deploying - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Pages - uses: actions/configure-pages@v5 - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - # Upload only the docs directory - path: 'docs' - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/docs/404.html b/docs/404.html index 6ff630fb15..2bdd43aa78 100644 --- a/docs/404.html +++ b/docs/404.html @@ -4,7 +4,7 @@ Redirecting… - + @@ -12,27 +12,8 @@

Not found

Redirecting…

-

Trying to find the right page.

+

Page not found. Taking you home.

- diff --git a/docs/assets/app.js b/docs/assets/app.js deleted file mode 100644 index 3209ea7d7d..0000000000 --- a/docs/assets/app.js +++ /dev/null @@ -1,54 +0,0 @@ -(function() { - const qs = (sel) => document.querySelector(sel); - - const initIndexSearch = () => { - const input = document.querySelector("[data-index-search]"); - if (!input) return; - const targetSel = input.getAttribute("data-target"); - const target = targetSel ? qs(targetSel) : null; - const indexUrl = input.getAttribute("data-index-url"); - if (!target || !indexUrl) return; - - let cached = []; - fetch(indexUrl) - .then((resp) => resp.json()) - .then((data) => { cached = data.items || []; }) - .catch(() => { target.innerHTML = "

Index unavailable.

"; }); - - const render = (term) => { - if (!cached.length) return; - const value = term.trim().toLowerCase(); - const results = cached.filter((row) => { - if (!value) return false; - return row.cve_id.toLowerCase().includes(value) || - (row.top_languages || []).join(" ").toLowerCase().includes(value) || - String(row.max_score || "").includes(value); - }).slice(0, 40); - - if (!results.length) { - target.innerHTML = "

No matches yet.

"; - return; - } - - target.innerHTML = results.map((row) => { - const langs = (row.top_languages || []).map((lang) => `${lang}`).join(" "); - return `
- -
- ${row.high_confidence} high - ${row.medium_confidence} med - ${row.poc_count} PoCs -
-
Max score ${row.max_score || 0}
-
${langs}
-
`; - }).join(""); - }; - - input.addEventListener("input", (e) => render(e.target.value)); - }; - - document.addEventListener("DOMContentLoaded", () => { - initIndexSearch(); - }); -})(); diff --git a/docs/assets/cve.js b/docs/assets/cve.js deleted file mode 100644 index 54eabe4d9a..0000000000 --- a/docs/assets/cve.js +++ /dev/null @@ -1,167 +0,0 @@ -(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 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 getDescriptionText(data) { - const desc = (data?.description || "").trim(); - if (desc) return desc; - const kevDesc = (data?.kev?.short_description || "").trim(); - if (kevDesc) return kevDesc; - return "No description available."; - } - - function hasKevData(kev) { - if (!kev || typeof kev !== "object") return false; - return Boolean( - (kev.short_description && kev.short_description.trim()) || - kev.date_added || - kev.due_date || - kev.required_action || - kev.notes - ); - } - - function renderFacts(data) { - const pocCount = data.poc_count ?? (Array.isArray(data.poc_links) ? data.poc_links.length : Array.isArray(data.poc) ? data.poc.length : undefined); - const items = []; - const vendorValue = data.vendor || "Unknown vendor"; - const productValue = data.product || "Unknown product"; - const epssValue = typeof data.epss === "number" ? data.epss.toFixed(3) : "n/a"; - const percentileValue = typeof data.percentile === "number" ? `${Math.round(data.percentile * 100)}th` : "n/a"; - const pocValue = pocCount ?? 0; - - items.push({ label: "Vendor", value: vendorValue }); - items.push({ label: "Product", value: productValue }); - items.push({ label: "EPSS", value: epssValue }); - items.push({ label: "Percentile", value: percentileValue }); - items.push({ label: "PoCs", value: pocValue }); - if (hasKevData(data.kev)) items.push({ label: "KEV status", value: data.kev.date_added ? `Added ${data.kev.date_added}` : "Listed" }); - - if (items.length === 0) { - factsEl.innerHTML = `
No overview data yet.
`; - return; - } - - factsEl.innerHTML = items - .map((item) => `
${item.value}${item.label}
`) - .join(""); - } - - function renderPocs(links) { - pocRowsEl.innerHTML = ""; - if (!links || links.length === 0) { - pocRowsEl.innerHTML = 'No PoC links available.'; - return; - } - pocRowsEl.innerHTML = links - .map((link) => `${link}`) - .join(""); - } - - function renderMeta(data) { - const pills = []; - if (data.vendor) pills.push(`Vendor: ${data.vendor}`); - if (data.product) pills.push(`Product: ${data.product}`); - if (hasKevData(data.kev)) pills.push("On KEV list"); - - metaEl.innerHTML = pills.map((text) => `${text}`).join(""); - } - - function renderKev(kev) { - if (!hasKevData(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]) => `${k}${v}`).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; - const desc = getDescriptionText(data); - summaryEl.textContent = desc; - renderFacts(data); - renderPocs(data.poc_links || data.poc || []); - renderKev(data.kev); - renderMeta(data); - detailSection.style.display = ""; - notFoundSection.style.display = "none"; - return; - } catch (err) { - console.warn("API lookup failed, trying CVE_list.json", err); - } - - try { - const fallback = await fetchFromList(cveId); - titleEl.textContent = fallback.cve; - const desc = getDescriptionText(fallback); - summaryEl.textContent = desc; - renderFacts(fallback); - renderPocs(fallback.poc_links || fallback.poc || []); - renderKev(null); - renderMeta(fallback); - detailSection.style.display = ""; - notFoundSection.style.display = "none"; - } 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); -})(); diff --git a/docs/assets/home.js b/docs/assets/home.js deleted file mode 100644 index 1af4017edd..0000000000 --- a/docs/assets/home.js +++ /dev/null @@ -1,79 +0,0 @@ -(function () { - function cardTemplate(item) { - return ` -
- -
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" : ""}
-

${item.summary || "No description."}

- ${item.vendor ? `
${item.vendor}
` : ""} - ${item.product ? `
${item.product}
` : ""} -
- `; - } - - function renderCards(gridId, items) { - const el = document.getElementById(gridId); - if (!el) return; - if (!items || items.length === 0) { - el.innerHTML = '

No data available.

'; - 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) => `${row.cve}`).join(", ") || "None"; - - const epssCount = (diff.new_high_epss || []).length; - const epssExamples = (diff.new_high_epss || []).slice(0, 5).map((row) => `${row.cve}`).join(", ") || "None"; - - const moverCount = (diff.epss_movers || []).length; - const moverExamples = (diff.epss_movers || []).slice(0, 5).map((row) => `${row.cve} (${row.delta.toFixed(3)})`).join(", ") || "None"; - - tbody.innerHTML = ` - - New KEV entries - ${kevCount} - ${kevExamples} - - - New high EPSS - ${epssCount} - ${epssExamples} - - - Top EPSS movers - ${moverCount} - ${moverExamples} - - `; - } - - 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); -})(); diff --git a/docs/assets/site.js b/docs/assets/site.js deleted file mode 100644 index 1097fc82de..0000000000 --- a/docs/assets/site.js +++ /dev/null @@ -1,20 +0,0 @@ -(function () { - function bindColumnFilters() { - const filterInputs = document.querySelectorAll("[data-filter-table]"); - filterInputs.forEach((input) => { - const table = document.getElementById(input.dataset.filterTable); - if (!table) return; - input.addEventListener("input", () => { - const term = input.value.trim().toLowerCase(); - for (const row of table.querySelectorAll("tbody tr")) { - const text = row.innerText.toLowerCase(); - row.style.display = text.includes(term) ? "" : "none"; - } - }); - }); - } - - document.addEventListener("DOMContentLoaded", () => { - bindColumnFilters(); - }); -})(); diff --git a/docs/assets/style.css b/docs/assets/style.css deleted file mode 100644 index bd6b4f6be4..0000000000 --- a/docs/assets/style.css +++ /dev/null @@ -1,97 +0,0 @@ -:root { - --bg: #05070d; - --panel: #0d1020; - --panel-2: #11162b; - --text: #f3f4ff; - --muted: #8fa2c8; - --accent: #7ef1d3; - --accent-2: #5bc0eb; - --warn: #ffb86c; - --success: #6ef2a6; - --border: #1f2742; - --shadow: 0 18px 45px rgba(0,0,0,0.35); - font-family: "Space Grotesk", "Inter", "Helvetica Neue", system-ui, sans-serif; - line-height: 1.55; -} - -* { box-sizing: border-box; } -body { - margin: 0; - background: radial-gradient(circle at 20% 20%, rgba(91,192,235,0.08), transparent 25%), radial-gradient(circle at 80% 0%, rgba(126,241,211,0.08), transparent 23%), var(--bg); - color: var(--text); -} -a { color: var(--accent); text-decoration: none; } -a:hover { text-decoration: underline; } -code { background: rgba(255,255,255,0.04); padding: 2px 6px; border-radius: 6px; color: var(--accent-2); } - -.wrap { width: min(1200px, 94vw); margin: 0 auto; padding: 1.5rem 0; } - -.topbar { position: sticky; top: 0; z-index: 10; background: rgba(13,16,32,0.85); backdrop-filter: blur(10px); border-bottom: 1px solid var(--border); } -.topbar .wrap { display: flex; justify-content: space-between; align-items: center; padding: 1rem 0; } -.brand a { font-weight: 700; letter-spacing: 0.5px; color: var(--text); } -.brand .dot { color: var(--accent); margin-right: 4px; } -nav a { margin-left: 1rem; color: var(--muted); font-weight: 600; } -nav a:hover { color: var(--accent); } - -h1, h2, h3, h4 { margin: 0 0 0.5rem; line-height: 1.25; } -p { margin: 0 0 0.75rem; } -.muted { color: var(--muted); } -.small { font-size: 0.9rem; } -.eyebrow { text-transform: uppercase; letter-spacing: 0.15em; font-size: 0.8rem; color: var(--accent); margin-bottom: 0.35rem; } -.lede { color: var(--muted); max-width: 60ch; } - -.hero { display: grid; grid-template-columns: 2fr 1fr; gap: 1.5rem; align-items: center; padding: 1rem 0 2rem; } -.hero-panel { background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 1rem; box-shadow: var(--shadow); display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0.75rem; } -.stat .label { color: var(--muted); font-size: 0.9rem; } -.stat .value { font-size: 1.9rem; font-weight: 700; } - -.cta-row { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: 1rem; } -.btn { background: linear-gradient(90deg, var(--accent), var(--accent-2)); color: #041019; padding: 0.75rem 1rem; border-radius: 12px; font-weight: 700; border: none; display: inline-block; } -.btn.ghost { background: transparent; color: var(--text); border: 1px solid var(--border); } -.text-link { color: var(--accent); font-weight: 600; } - -.section-header { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 0.75rem; } - -.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; } -.card { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 1rem; box-shadow: var(--shadow); } -.card-title { font-weight: 700; margin-bottom: 0.4rem; } -.meta-row { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; margin-bottom: 0.35rem; } - -.pill { display: inline-flex; align-items: center; gap: 4px; padding: 0.25rem 0.6rem; border-radius: 999px; background: rgba(255,255,255,0.04); border: 1px solid var(--border); color: var(--text); font-size: 0.85rem; } -.pill.ghost { background: transparent; color: var(--muted); } -.pill.warn { border-color: var(--warn); color: var(--warn); } -.pill.tier-high { border-color: var(--success); color: var(--success); } -.pill.tier-medium { border-color: var(--accent-2); color: var(--accent-2); } -.pill.tier-low { border-color: var(--muted); color: var(--muted); } -.pill.tiny { font-size: 0.75rem; padding: 0.15rem 0.4rem; } - -.input { width: 100%; padding: 0.75rem; border-radius: 12px; border: 1px solid var(--border); background: var(--panel-2); color: var(--text); margin: 0.5rem 0 1rem; } - -.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow); background: var(--panel); } -table { width: 100%; border-collapse: collapse; } -th, td { padding: 0.85rem 1rem; border-bottom: 1px solid var(--border); text-align: left; } -th { background: #0f1326; color: var(--muted); font-weight: 600; letter-spacing: 0.02em; } -tr:last-child td { border-bottom: none; } - -.matches ul { list-style: none; padding: 0; margin: 0.35rem 0 0; } -.matches li { margin-bottom: 0.25rem; color: var(--muted); } - -.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; } -.list { list-style: none; padding: 0; margin: 0.35rem 0; } -.list li { padding: 0.4rem 0; border-bottom: 1px solid var(--border); } -.list li:last-child { border-bottom: none; } - -.pill-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.8rem 0; } - -.footer { border-top: 1px solid var(--border); margin-top: 2rem; } -.footer-inner { display: flex; flex-wrap: wrap; gap: 1rem; padding: 1rem 0; color: var(--muted); } - -@media (max-width: 840px) { - .hero { grid-template-columns: 1fr; } - nav { display: none; } -} - -@media (max-width: 620px) { - .card-grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } - th, td { padding: 0.65rem; } -} diff --git a/docs/cve/index.html b/docs/cve/index.html deleted file mode 100644 index 2f69da0747..0000000000 --- a/docs/cve/index.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - CVE Details - CVE PoC Hub - - - - - -
-
-

CVE detail

-

Loading…

-

Fetching CVE data.

-
-
- - - - -
- - - diff --git a/docs/diffs/index.html b/docs/diffs/index.html deleted file mode 100644 index 6e3ca12ee9..0000000000 --- a/docs/diffs/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - CVE PoC Hub - - - - - - -
-
-
-

New KEV entries

- Only the recent additions -
-
- - - - - - - - - - - - - -
CVEVendorProductEPSSPercentileDate AddedDue
CVE-2025-6218RARLABWinRAR0.000 0th2025-12-092025-12-30
-
-
-
- - - \ No newline at end of file diff --git a/docs/epss/index.html b/docs/epss/index.html deleted file mode 100644 index 97e3be9827..0000000000 --- a/docs/epss/index.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - CVE PoC Hub - - - - - - -
-
-
-

EPSS highlights

- High-probability CVEs that are not in KEV. -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CVEEPSSPercentilePoCsSummary
CVE-2025-89430.65898th1The 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...
CVE-2025-85180.33997th1A vulnerability was found in givanz Vvveb 1.0.5. It has been rated as critical. Affected by this issue is the function Save of the file admin/controller/editor/code.php of the component Code Editor. The manipulation l...
CVE-2025-87300.11993th2A vulnerability was found in Belkin F9K1009 and F9K1010 2.00.04/2.00.09 and classified as critical. Affected by this issue is some unknown functionality of the component Web Interface. The manipulation leads to hard-c...
CVE-2025-77950.09693th3A vulnerability, which was classified as critical, has been found in Tenda FH451 1.0.0.9. Affected by this issue is the function fromP2pListFilter of the file /goform/P2pListFilter. The manipulation of the argument pa...
CVE-2025-90900.09292th4A vulnerability was identified in Tenda AC20 16.03.08.12. Affected is the function websFormDefine of the file /goform/telnet of the component Telnet Service. The manipulation leads to command injection. It is possible...
CVE-2025-80850.07892th1The Ditty WordPress plugin before 3.1.58 lacks authorization and authentication for requests to its displayItems endpoint, allowing unauthenticated visitors to make requests to arbitrary URLs.
-
-
-
- - - \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 9548c3c72d..3a1dffb3b7 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,249 +6,52 @@ CVE PoC Hub - -
-
-
-

CVE PoC Hub

-

Search PoCs, KEV, and EPSS quickly—no filler.

-
-
- -
-
-
264KEV entries tracked
-
6High-EPSS not in KEV
-
1New KEV in last 30 days
-
- -
+
+

Find exploit writeups and PoCs instantly

+

Search by CVE id, vendor, product, or keyword.

+
+ Linked PoCs + MITRE CVE pages + Vendor / product filters + Supports negative terms (e.g. -windows) +
+
+ +
+ +
-
-
-

Trending PoCs

- Current year, updated in the last 4 days -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StarsUpdatedNameDescription
155 minutes agoCVE-2025-61882-CVE-2025-61884🔍 Detect vulnerabilities CVE-2025-61882 and CVE-2025-61884 in Oracle E-Business Suite to help secure your systems from potential remote code execution threats.
11 hour agoCVE-2025-54253-Exploit-Demo🐙 CVE-2025-54253 exploit demo for Adobe AEM Forms on JEE: OGNL injection to RCE with PoC, Python 3.10 exploit code, reproducer and mitigation guidance.
11 hour agoCVE-2025-54424CVE-2025-54424: 1Panel TLS client cert bypass enables RCE via forged CN 'panel_client' using a bundled scanning and exploitation tool. Affected: <= v2.0.5. 🔐
3602 hours agoNext.js-RSC-RCE-Scanner-CVE-2025-66478A command-line scanner for batch detection of Next.js application versions and determining if they are affected by CVE-2025-66478 vulnerability.
12 hours agoCVE-2025-13780A comprehensive vulnerability scanner for CVE-2025-13780, a Remote Code Execution (RCE) vulnerability in pgAdmin 4 versions ≤ 8.14.
210 hours agoCVE-2025-6218-WinRAR-RCE-POCComprehensive analysis and proof-of-concept for CVE-2025-6218 - WinRAR path traversal RCE vulnerability affecting versions 7.11 and earlier
111 hours agoCVE-2025-55182-React2Shell-ExploitA proof-of-concept tool for demonstrating the critical React2Shell vulnerability
413 hours agoCVE-2025-66478-POCCVE-2025-66478 Proof of Concept
422 hours agoCVE-2025-65318-and-CVE-2025-65319Insecure attachment handling when using Canary Mail or Blue mail
781 day agoBlackash-CVE-2025-55182CVE-2025-55182
171 day agoCVE-2025-55182a critical Remote Code Execution (RCE) vulnerability in React Server Components (RSC). It also includes a realistic "Lab Environment" to safely test and understand the vulnerability.
31 day agoCVE-2025-54100CVE-2025-54100 (CVSS 7.8 High) is a command injection vulnerability in the Invoke-WebRequest cmdlet of Windows PowerShell 5.1. It arises from improper neutralization of special elements during the automatic parsing of Web responses.
21 day agoCVE-2025-31702Repository with tools, exploits, and material associated with the analysis and discovery process of CVE-2025-31702 and other related security issues.
11 day agoCVE-2025-55182React2Shell Vulnerability
11 day agoBlackash-CVE-2025-13780CVE-2025-13780
22 days agoCVE-2025-55182This project provides a fully functional demonstration of CVE-2025-55182 (React2Shell) - a critical Remote Code Execution vulnerability in React Server Components and Next.js.
12 days agoreact2shell-scanner-CVE-2025-55182React2shell-web-scanner
12 days agoCVE-2025-55182-WafCVE-2025-55182 RCE vulnerability in Next.js/React RSC servers (exploit and scanner)
12 days agoCVE-2025-55182A command-line tool for detecting CVE-2025-55182 and CVE-2025-66478 in Next.js applications using React Server Components.
12 days agoCVE-2025-9074_DAEMON_KILLERThe Ultimate DAEMON_KILLER. Control is an illusion. This Exploit forces CVE-2025-9074 to break the Docker cage. Advanced Container Escape & Root Escalation toolkit. Verify the vulnerability, take the host, destroy the logs. > We Are Fsociety_
-
-
- -
-
-

High EPSS not in KEV

- Sorted by score -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CVEEPSSPercentilePoCsSummary
CVE-2025-89430.65898th1The 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...
CVE-2025-85180.33997th1A vulnerability was found in givanz Vvveb 1.0.5. It has been rated as critical. Affected by this issue is the function Save of the file admin/controller/editor/code.php of the component Code Editor. The manipulation l...
CVE-2025-87300.11993th2A vulnerability was found in Belkin F9K1009 and F9K1010 2.00.04/2.00.09 and classified as critical. Affected by this issue is some unknown functionality of the component Web Interface. The manipulation leads to hard-c...
CVE-2025-77950.09693th3A vulnerability, which was classified as critical, has been found in Tenda FH451 1.0.0.9. Affected by this issue is the function fromP2pListFilter of the file /goform/P2pListFilter. The manipulation of the argument pa...
CVE-2025-90900.09292th4A vulnerability was identified in Tenda AC20 16.03.08.12. Affected is the function websFormDefine of the file /goform/telnet of the component Telnet Service. The manipulation leads to command injection. It is possible...
CVE-2025-80850.07892th1The Ditty WordPress plugin before 3.1.58 lacks authorization and authentication for requests to its displayItems endpoint, allowing unauthenticated visitors to make requests to arbitrary URLs.
-
-
+
+

Latest PoC examples

+
+ + + + + +
StarsUpdatedNameDescription
No recent PoCs.
+
+
- - + - \ No newline at end of file + diff --git a/docs/kev/index.html b/docs/kev/index.html deleted file mode 100644 index 49a4c21e1e..0000000000 --- a/docs/kev/index.html +++ /dev/null @@ -1,2423 +0,0 @@ - - - - - - CVE PoC Hub - - - - - - -
-
-
-

KEV catalog

- Filter by CVE, vendor, or product. -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CVEVendorProductEPSSPercentileDate AddedDue
CVE-2025-7775CitrixNetScaler0.17495th2025-08-262025-08-28
CVE-2025-9377TP-LinkMultiple Routers0.14694th2025-09-032025-09-24
CVE-2025-8876N-ableN-Central0.13994th2025-08-132025-08-20
CVE-2025-8875N-ableN-Central0.05189th2025-08-132025-08-20
CVE-2025-8088RARLABWinRAR0.03286th2025-08-122025-09-02
CVE-2024-0012Palo Alto NetworksPAN-OS0.000 0th2024-11-182024-12-09
CVE-2024-0519GoogleChromium V80.000 0th2024-01-172024-02-07
CVE-2024-0769D-LinkDIR-859 Router0.000 0th2025-06-252025-07-16
CVE-2024-1086LinuxKernel0.000 0th2024-05-302024-06-20
CVE-2024-11120GeoVisionMultiple Devices0.000 0th2025-05-072025-05-28
CVE-2024-11182MDaemonEmail Server0.000 0th2025-05-192025-06-09
CVE-2024-11667ZyxelMultiple Firewalls0.000 0th2024-12-032024-12-24
CVE-2024-11680ProjectSendProjectSend0.000 0th2024-12-032024-12-24
CVE-2024-1212ProgressKemp LoadMaster0.000 0th2024-11-182024-12-09
CVE-2024-12356BeyondTrustPrivileged Remote Access (PRA) and Remote Support (RS)0.000 0th2024-12-192024-12-27
CVE-2024-12686BeyondTrustPrivileged Remote Access (PRA) and Remote Support (RS)0.000 0th2025-01-132025-02-03
CVE-2024-12987DrayTekVigor Routers0.000 0th2025-05-152025-06-05
CVE-2024-13159IvantiEndpoint Manager (EPM)0.000 0th2025-03-102025-03-31
CVE-2024-13160IvantiEndpoint Manager (EPM)0.000 0th2025-03-102025-03-31
CVE-2024-13161IvantiEndpoint Manager (EPM)0.000 0th2025-03-102025-03-31
CVE-2024-1709ConnectWiseScreenConnect0.000 0th2024-02-222024-02-29
CVE-2024-20353CiscoAdaptive Security Appliance (ASA) and Firepower Threat Defense (FTD)0.000 0th2024-04-242024-05-01
CVE-2024-20359CiscoAdaptive Security Appliance (ASA) and Firepower Threat Defense (FTD)0.000 0th2024-04-242024-05-01
CVE-2024-20399CiscoNX-OS0.000 0th2024-07-022024-07-23
CVE-2024-20439CiscoSmart Licensing Utility0.000 0th2025-03-312025-04-21
CVE-2024-20481CiscoAdaptive Security Appliance (ASA) and Firepower Threat Defense (FTD)0.000 0th2024-10-242024-11-14
CVE-2024-20767AdobeColdFusion0.000 0th2024-12-162025-01-06
CVE-2024-20953OracleAgile Product Lifecycle Management (PLM)0.000 0th2025-02-242025-03-17
CVE-2024-21287OracleAgile Product Lifecycle Management (PLM)0.000 0th2024-11-212024-12-12
CVE-2024-21338MicrosoftWindows0.000 0th2024-03-042024-03-25
CVE-2024-21351MicrosoftWindows0.000 0th2024-02-132024-03-05
CVE-2024-21410MicrosoftExchange Server0.000 0th2024-02-152024-03-07
CVE-2024-21412MicrosoftWindows0.000 0th2024-02-132024-03-05
CVE-2024-21413MicrosoftOffice Outlook0.000 0th2025-02-062025-02-27
CVE-2024-21762FortinetFortiOS0.000 0th2024-02-092024-02-16
CVE-2024-21887IvantiConnect Secure and Policy Secure0.000 0th2024-01-102024-01-22
CVE-2024-21893IvantiConnect Secure, Policy Secure, and Neurons0.000 0th2024-01-312024-02-02
CVE-2024-23113FortinetMultiple Products0.000 0th2024-10-092024-10-30
CVE-2024-23222AppleMultiple Products0.000 0th2024-01-232024-02-13
CVE-2024-23296AppleMultiple Products0.000 0th2024-03-062024-03-27
CVE-2024-23692RejettoHTTP File Server0.000 0th2024-07-092024-07-30
CVE-2024-23897JenkinsJenkins Command Line Interface (CLI)0.000 0th2024-08-192024-09-09
CVE-2024-24919Check PointQuantum Security Gateways0.000 0th2024-05-302024-06-20
CVE-2024-26169MicrosoftWindows0.000 0th2024-06-132024-07-04
CVE-2024-27198JetBrainsTeamCity0.000 0th2024-03-072024-03-28
CVE-2024-27348ApacheHugeGraph-Server0.000 0th2024-09-182024-10-09
CVE-2024-27443SynacorZimbra Collaboration Suite (ZCS)0.000 0th2025-05-192025-06-09
CVE-2024-28986SolarWindsWeb Help Desk0.000 0th2024-08-152024-09-05
CVE-2024-28987SolarWindsWeb Help Desk0.000 0th2024-10-152024-11-05
CVE-2024-28995SolarWindsServ-U0.000 0th2024-07-172024-08-07
CVE-2024-29059Microsoft.NET Framework0.000 0th2025-02-042025-02-25
CVE-2024-29745AndroidPixel0.000 0th2024-04-042024-04-25
CVE-2024-29748AndroidPixel0.000 0th2024-04-042024-04-25
CVE-2024-29824IvantiEndpoint Manager (EPM)0.000 0th2024-10-022024-10-23
CVE-2024-29988MicrosoftSmartScreen Prompt0.000 0th2024-04-302024-05-21
CVE-2024-30040MicrosoftWindows0.000 0th2024-05-142024-06-04
CVE-2024-30051MicrosoftDWM Core Library0.000 0th2024-05-142024-06-04
CVE-2024-30088MicrosoftWindows0.000 0th2024-10-152024-11-05
CVE-2024-32113ApacheOFBiz0.000 0th2024-08-072024-08-28
CVE-2024-3272D-LinkMultiple NAS Devices0.000 0th2024-04-112024-05-02
CVE-2024-3273D-LinkMultiple NAS Devices0.000 0th2024-04-112024-05-02
CVE-2024-32896AndroidPixel0.000 0th2024-06-132024-07-04
CVE-2024-3393Palo Alto NetworksPAN-OS0.000 0th2024-12-302025-01-20
CVE-2024-3400Palo Alto NetworksPAN-OS0.000 0th2024-04-122024-04-19
CVE-2024-34102AdobeCommerce and Magento Open Source0.000 0th2024-07-172024-08-07
CVE-2024-35250MicrosoftWindows0.000 0th2024-12-162025-01-06
CVE-2024-36401OSGeoGeoServer0.000 0th2024-07-152024-08-05
CVE-2024-36971AndroidKernel0.000 0th2024-08-072024-08-28
CVE-2024-37085VMwareESXi0.000 0th2024-07-302024-08-20
CVE-2024-37383RoundcubeWebmail0.000 0th2024-10-242024-11-14
CVE-2024-38014MicrosoftWindows0.000 0th2024-09-102024-10-01
CVE-2024-38080MicrosoftWindows0.000 0th2024-07-092024-07-30
CVE-2024-38094MicrosoftSharePoint0.000 0th2024-10-222024-11-12
CVE-2024-38112MicrosoftWindows0.000 0th2024-07-092024-07-30
CVE-2024-38178MicrosoftWindows0.000 0th2024-08-132024-09-03
CVE-2024-38189MicrosoftProject0.000 0th2024-08-132024-09-03
CVE-2024-38193MicrosoftWindows0.000 0th2024-08-132024-09-03
CVE-2024-38213MicrosoftWindows0.000 0th2024-08-132024-09-03
CVE-2024-38217MicrosoftWindows0.000 0th2024-09-102024-10-01
CVE-2024-38475ApacheHTTP Server0.000 0th2025-05-012025-05-22
CVE-2024-38812VMwarevCenter Server0.000 0th2024-11-202024-12-11
CVE-2024-38813VMwarevCenter Server0.000 0th2024-11-202024-12-11
CVE-2024-38856ApacheOFBiz0.000 0th2024-08-272024-09-17
CVE-2024-39717VersaDirector0.000 0th2024-08-232024-09-13
CVE-2024-4040CrushFTPCrushFTP0.000 0th2024-04-242024-05-01
CVE-2024-40711VeeamBackup & Replication0.000 0th2024-10-172024-11-07
CVE-2024-40766SonicWallSonicOS0.000 0th2024-09-092024-09-30
CVE-2024-40890ZyxelDSL CPE Devices0.000 0th2025-02-112025-03-04
CVE-2024-40891ZyxelDSL CPE Devices0.000 0th2025-02-112025-03-04
CVE-2024-41710MitelSIP Phones0.000 0th2025-02-122025-03-05
CVE-2024-41713MitelMiCollab0.000 0th2025-01-072025-01-28
CVE-2024-42009RoundcubeWebmail0.000 0th2025-06-092025-06-30
CVE-2024-43047QualcommMultiple Chipsets0.000 0th2024-10-082024-10-29
CVE-2024-43093AndroidFramework0.000 0th2024-11-072024-11-28
CVE-2024-43451MicrosoftWindows0.000 0th2024-11-122024-12-03
CVE-2024-43572MicrosoftWindows0.000 0th2024-10-082024-10-29
CVE-2024-4358ProgressTelerik Report Server0.000 0th2024-06-132024-07-04
CVE-2024-44308AppleMultiple Products0.000 0th2024-11-212024-12-12
CVE-2024-44309AppleMultiple Products0.000 0th2024-11-212024-12-12
CVE-2024-45195ApacheOFBiz0.000 0th2025-02-042025-02-25
CVE-2024-45519SynacorZimbra Collaboration Suite (ZCS)0.000 0th2024-10-032024-10-24
CVE-2024-4577PHP GroupPHP0.000 0th2024-06-122024-07-03
CVE-2024-4610ArmMali GPU Kernel Driver0.000 0th2024-06-122024-07-03
CVE-2024-4671GoogleChromium0.000 0th2024-05-132024-06-03
CVE-2024-47575FortinetFortiManager0.000 0th2024-10-232024-11-13
CVE-2024-4761GoogleChromium V80.000 0th2024-05-162024-06-06
CVE-2024-48248NAKIVOBackup and Replication0.000 0th2025-03-192025-04-09
CVE-2024-4879ServiceNowUtah, Vancouver, and Washington DC Now Platform0.000 0th2024-07-292024-08-19
CVE-2024-4885ProgressWhatsUp Gold0.000 0th2025-03-032025-03-24
CVE-2024-49035MicrosoftPartner Center0.000 0th2025-02-252025-03-18
CVE-2024-49039MicrosoftWindows0.000 0th2024-11-122024-12-03
CVE-2024-49138MicrosoftWindows0.000 0th2024-12-102024-12-31
CVE-2024-4947GoogleChromium V80.000 0th2024-05-202024-06-10
CVE-2024-50302LinuxKernel0.000 0th2025-03-042025-03-25
CVE-2024-50603AviatrixControllers0.000 0th2025-01-162025-02-06
CVE-2024-50623CleoMultiple Products0.000 0th2024-12-132025-01-03
CVE-2024-51378CyberPersonsCyberPanel0.000 0th2024-12-042024-12-25
CVE-2024-51567CyberPersonsCyberPanel0.000 0th2024-11-072024-11-28
CVE-2024-5217ServiceNowUtah, Vancouver, and Washington DC Now Platform0.000 0th2024-07-292024-08-19
CVE-2024-5274GoogleChromium V80.000 0th2024-05-282024-06-18
CVE-2024-53104LinuxKernel0.000 0th2025-02-052025-02-26
CVE-2024-53150LinuxKernel0.000 0th2025-04-092025-04-30
CVE-2024-53197LinuxKernel0.000 0th2025-04-092025-04-30
CVE-2024-53704SonicWallSonicOS0.000 0th2025-02-182025-03-11
CVE-2024-54085AMIMegaRAC SPx0.000 0th2025-06-252025-07-16
CVE-2024-55550MitelMiCollab0.000 0th2025-01-072025-01-28
CVE-2024-55591FortinetFortiOS and FortiProxy0.000 0th2025-01-142025-01-21
CVE-2024-55956CleoMultiple Products0.000 0th2024-12-172025-01-07
CVE-2024-56145Craft CMSCraft CMS0.000 0th2025-06-022025-06-23
CVE-2024-57727SimpleHelpSimpleHelp0.000 0th2025-02-132025-03-06
CVE-2024-57968AdvantiveVeraCore0.000 0th2025-03-102025-03-31
CVE-2024-58136YiiframeworkYii0.000 0th2025-05-022025-05-23
CVE-2024-5910Palo Alto NetworksExpedition0.000 0th2024-11-072024-11-28
CVE-2024-6047GeoVisionMultiple Devices0.000 0th2025-05-072025-05-28
CVE-2024-6670ProgressWhatsUp Gold0.000 0th2024-09-162024-10-07
CVE-2024-7262KingsoftWPS Office0.000 0th2024-09-032024-09-24
CVE-2024-7593IvantiVirtual Traffic Manager0.000 0th2024-09-242024-10-15
CVE-2024-7965GoogleChromium V80.000 0th2024-08-282024-09-18
CVE-2024-7971GoogleChromium V80.000 0th2024-08-262024-09-16
CVE-2024-8068CitrixSession Recording0.000 0th2025-08-252025-09-15
CVE-2024-8069CitrixSession Recording0.000 0th2025-08-252025-09-15
CVE-2024-8190IvantiCloud Services Appliance0.000 0th2024-09-132024-10-04
CVE-2024-8956PTZOpticsPT30X-SDI/NDI Cameras0.000 0th2024-11-042024-11-25
CVE-2024-8957PTZOpticsPT30X-SDI/NDI Cameras0.000 0th2024-11-042024-11-25
CVE-2024-8963IvantiCloud Services Appliance (CSA)0.000 0th2024-09-192024-10-10
CVE-2024-9379IvantiCloud Services Appliance (CSA)0.000 0th2024-10-092024-10-30
CVE-2024-9380IvantiCloud Services Appliance (CSA)0.000 0th2024-10-092024-10-30
CVE-2024-9463Palo Alto NetworksExpedition0.000 0th2024-11-142024-12-05
CVE-2024-9465Palo Alto NetworksExpedition0.000 0th2024-11-142024-12-05
CVE-2024-9474Palo Alto NetworksPAN-OS0.000 0th2024-11-182024-12-09
CVE-2024-9537ScienceLogicSL10.000 0th2024-10-212024-11-11
CVE-2024-9680MozillaFirefox0.000 0th2024-10-152024-11-05
CVE-2025-0108Palo Alto NetworksPAN-OS0.000 0th2025-02-182025-03-11
CVE-2025-0111Palo Alto NetworksPAN-OS0.000 0th2025-02-202025-03-13
CVE-2025-0282IvantiConnect Secure, Policy Secure, and ZTA Gateways0.000 0th2025-01-082025-01-15
CVE-2025-04117-Zip7-Zip0.000 0th2025-02-062025-02-27
CVE-2025-0994TrimbleCityworks0.000 0th2025-02-072025-02-28
CVE-2025-10035FortraGoAnywhere MFT0.000 0th2025-09-292025-10-20
CVE-2025-10585GoogleChromium V80.000 0th2025-09-232025-10-14
CVE-2025-1316EdimaxIC-7100 IP Camera0.000 0th2025-03-192025-04-09
CVE-2025-1976BroadcomBrocade Fabric OS0.000 0th2025-04-282025-05-19
CVE-2025-20281CiscoIdentity Services Engine0.000 0th2025-07-282025-08-18
CVE-2025-20333CiscoSecure Firewall Adaptive Security Appliance and Secure Firewall Threat Defense0.000 0th2025-09-252025-09-26
CVE-2025-20337CiscoIdentity Services Engine0.000 0th2025-07-282025-08-18
CVE-2025-20352CiscoIOS and IOS XE0.000 0th2025-09-292025-10-20
CVE-2025-20362CiscoSecure Firewall Adaptive Security Appliance and Secure Firewall Threat Defense0.000 0th2025-09-252025-09-26
CVE-2025-21043SamsungMobile Devices0.000 0th2025-10-022025-10-23
CVE-2025-21333MicrosoftWindows0.000 0th2025-01-142025-02-04
CVE-2025-21334MicrosoftWindows0.000 0th2025-01-142025-02-04
CVE-2025-21335MicrosoftWindows0.000 0th2025-01-142025-02-04
CVE-2025-21391MicrosoftWindows0.000 0th2025-02-112025-03-04
CVE-2025-21418MicrosoftWindows0.000 0th2025-02-112025-03-04
CVE-2025-21479QualcommMultiple Chipsets0.000 0th2025-06-032025-06-24
CVE-2025-21480QualcommMultiple Chipsets0.000 0th2025-06-032025-06-24
CVE-2025-21590JuniperJunos OS0.000 0th2025-03-132025-04-03
CVE-2025-22224VMwareESXi and Workstation0.000 0th2025-03-042025-03-25
CVE-2025-22225VMwareESXi0.000 0th2025-03-042025-03-25
CVE-2025-22226VMwareESXi, Workstation, and Fusion0.000 0th2025-03-042025-03-25
CVE-2025-22457IvantiConnect Secure, Policy Secure, and ZTA Gateways0.000 0th2025-04-042025-04-11
CVE-2025-23006SonicWallSMA1000 Appliances0.000 0th2025-01-242025-02-14
CVE-2025-23209Craft CMSCraft CMS0.000 0th2025-02-202025-03-13
CVE-2025-24016WazuhWazuh Server0.000 0th2025-06-102025-07-01
CVE-2025-24054MicrosoftWindows0.000 0th2025-04-172025-05-08
CVE-2025-24085AppleMultiple Products0.000 0th2025-01-292025-02-19
CVE-2025-24200AppleiOS and iPadOS0.000 0th2025-02-122025-03-05
CVE-2025-24201AppleMultiple Products0.000 0th2025-03-132025-04-03
CVE-2025-24472FortinetFortiOS and FortiProxy0.000 0th2025-03-182025-04-08
CVE-2025-24813ApacheTomcat0.000 0th2025-04-012025-04-22
CVE-2025-24893XWikiPlatform0.000 0th2025-10-302025-11-20
CVE-2025-24983MicrosoftWindows0.000 0th2025-03-112025-04-01
CVE-2025-24984MicrosoftWindows0.000 0th2025-03-112025-04-01
CVE-2025-24985MicrosoftWindows0.000 0th2025-03-112025-04-01
CVE-2025-24989MicrosoftPower Pages0.000 0th2025-02-212025-03-14
CVE-2025-24991MicrosoftWindows0.000 0th2025-03-112025-04-01
CVE-2025-24993MicrosoftWindows0.000 0th2025-03-112025-04-01
CVE-2025-25181AdvantiveVeraCore0.000 0th2025-03-102025-03-31
CVE-2025-25257FortinetFortiWeb0.000 0th2025-07-182025-08-08
CVE-2025-26633MicrosoftWindows0.000 0th2025-03-112025-04-01
CVE-2025-27038QualcommMultiple Chipsets0.000 0th2025-06-032025-06-24
CVE-2025-27363FreeTypeFreeType0.000 0th2025-05-062025-05-27
CVE-2025-2746KenticoXperience CMS0.000 0th2025-10-202025-11-10
CVE-2025-2747KenticoXperience CMS0.000 0th2025-10-202025-11-10
CVE-2025-2775SysAidSysAid On-Prem0.000 0th2025-07-222025-08-12
CVE-2025-2776SysAidSysAid On-Prem0.000 0th2025-07-222025-08-12
CVE-2025-2783GoogleChromium Mojo0.000 0th2025-03-272025-04-17
CVE-2025-27915SynacorZimbra Collaboration Suite (ZCS)0.000 0th2025-10-072025-10-28
CVE-2025-27920SrimaxOutput Messenger0.000 0th2025-05-192025-06-09
CVE-2025-29824MicrosoftWindows0.000 0th2025-04-082025-04-29
CVE-2025-30066tj-actionschanged-files GitHub Action0.000 0th2025-03-182025-04-08
CVE-2025-30154reviewdogaction-setup GitHub Action0.000 0th2025-03-242025-04-14
CVE-2025-30397MicrosoftWindows0.000 0th2025-05-132025-06-03
CVE-2025-30400MicrosoftWindows0.000 0th2025-05-132025-06-03
CVE-2025-30406GladinetCentreStack0.000 0th2025-04-082025-04-29
CVE-2025-31161CrushFTPCrushFTP0.000 0th2025-04-072025-04-28
CVE-2025-31200AppleMultiple Products0.000 0th2025-04-172025-05-08
CVE-2025-31201AppleMultiple Products0.000 0th2025-04-172025-05-08
CVE-2025-31324SAPNetWeaver0.000 0th2025-04-292025-05-20
CVE-2025-32433ErlangErlang/OTP0.000 0th2025-06-092025-06-30
CVE-2025-32463SudoSudo0.000 0th2025-09-292025-10-20
CVE-2025-3248LangflowLangflow0.000 0th2025-05-052025-05-26
CVE-2025-32701MicrosoftWindows0.000 0th2025-05-132025-06-03
CVE-2025-32706MicrosoftWindows0.000 0th2025-05-132025-06-03
CVE-2025-32709MicrosoftWindows0.000 0th2025-05-132025-06-03
CVE-2025-32756FortinetMultiple Products0.000 0th2025-05-142025-06-04
CVE-2025-33053MicrosoftWindows0.000 0th2025-06-102025-07-01
CVE-2025-33073MicrosoftWindows0.000 0th2025-10-202025-11-10
CVE-2025-34028CommvaultCommand Center0.000 0th2025-05-022025-05-23
CVE-2025-35939Craft CMSCraft CMS0.000 0th2025-06-022025-06-23
CVE-2025-38352LinuxKernel0.000 0th2025-09-042025-09-25
CVE-2025-3928CommvaultWeb Server0.000 0th2025-04-282025-05-19
CVE-2025-3935ConnectWiseScreenConnect0.000 0th2025-06-022025-06-23
CVE-2025-4008SmartbeddedMeteobridge0.000 0th2025-10-022025-10-23
CVE-2025-42599QualitiaActive! Mail0.000 0th2025-04-282025-05-19
CVE-2025-42999SAPNetWeaver0.000 0th2025-05-152025-06-05
CVE-2025-43200AppleMultiple Products0.000 0th2025-06-162025-07-07
CVE-2025-43300AppleiOS, iPadOS, and macOS0.000 0th2025-08-212025-09-11
CVE-2025-4427IvantiEndpoint Manager Mobile (EPMM)0.000 0th2025-05-192025-06-09
CVE-2025-4428IvantiEndpoint Manager Mobile (EPMM)0.000 0th2025-05-192025-06-09
CVE-2025-4632SamsungMagicINFO 9 Server0.000 0th2025-05-222025-06-12
CVE-2025-47729TeleMessageTM SGNL0.000 0th2025-05-122025-06-02
CVE-2025-47812Wing FTP ServerWing FTP Server0.000 0th2025-07-142025-08-04
CVE-2025-47827IGELIGEL OS0.000 0th2025-10-142025-11-04
CVE-2025-48384GitGit0.000 0th2025-08-252025-09-15
CVE-2025-48543AndroidRuntime0.000 0th2025-09-042025-09-25
CVE-2025-48703CWPControl Web Panel0.000 0th2025-11-042025-11-25
CVE-2025-48927TeleMessageTM SGNL0.000 0th2025-07-012025-07-22
CVE-2025-48928TeleMessageTM SGNL0.000 0th2025-07-012025-07-22
CVE-2025-49704MicrosoftSharePoint0.000 0th2025-07-222025-07-23
CVE-2025-49706MicrosoftSharePoint0.000 0th2025-07-222025-07-23
CVE-2025-5086Dassault SystèmesDELMIA Apriso0.000 0th2025-09-112025-10-02
CVE-2025-53690SitecoreMultiple Products0.000 0th2025-09-042025-09-25
CVE-2025-53770MicrosoftSharePoint0.000 0th2025-07-202025-07-21
CVE-2025-5419GoogleChromium V80.000 0th2025-06-052025-06-26
CVE-2025-54236AdobeCommerce and Magento0.000 0th2025-10-242025-11-14
CVE-2025-54253AdobeExperience Manager (AEM) Forms0.000 0th2025-10-152025-11-05
CVE-2025-54309CrushFTPCrushFTP0.000 0th2025-07-222025-08-12
CVE-2025-54948Trend MicroApex One0.000 0th2025-08-182025-09-08
CVE-2025-55177Meta PlatformsWhatsApp0.000 0th2025-09-022025-09-23
CVE-2025-5777CitrixNetScaler ADC and Gateway0.000 0th2025-07-102025-07-11
CVE-2025-57819SangomaFreePBX0.000 0th2025-08-292025-09-19
CVE-2025-6218RARLABWinRAR0.000 0th2025-12-092025-12-30
CVE-2025-6543CitrixNetScaler ADC and Gateway0.000 0th2025-06-302025-07-21
CVE-2025-6554GoogleChromium V80.000 0th2025-07-022025-07-23
CVE-2025-6558GoogleChromium0.000 0th2025-07-222025-08-12
-
-
-
- - - \ No newline at end of file diff --git a/docs/logic.js b/docs/logic.js index 80f4060d0f..109ae379b6 100644 --- a/docs/logic.js +++ b/docs/logic.js @@ -7,6 +7,14 @@ function getSearchRoot() { return document.querySelector('[data-search-root]'); } +function getTrendingSection() { + return document.querySelector('[data-trending-section]'); +} + +function getTrendingBody() { + return document.getElementById('trending-body'); +} + function escapeHTML(str) { return str.replace(/[&<>"']/g, match => ({ '&': '&', @@ -51,7 +59,7 @@ function toggleDropdown(button) { window.toggleDropdown = toggleDropdown; function getCveLink(cveId) { - return `${cveId}`; + return `${cveId}`; } function prepareDataset(raw) { @@ -141,6 +149,8 @@ window.controls = controls; document.addEventListener('DOMContentLoaded', () => { const root = getSearchRoot(); + const trendingSection = getTrendingSection(); + const trendingBody = getTrendingBody(); if (!root) return; const results = root.querySelector('[data-results]'); @@ -160,11 +170,46 @@ document.addEventListener('DOMContentLoaded', () => { let currentSet = []; let debounceTimer; + function renderTrending(items) { + if (!trendingBody) return; + if (!items || items.length === 0) { + trendingBody.innerHTML = 'No recent PoCs.'; + return; + } + const rows = items.slice(0, 20).map(item => { + const stars = item.stars ?? ''; + const updated = escapeHTML(item.updated || ''); + const name = escapeHTML(item.name || ''); + const url = item.url || '#'; + const desc = escapeHTML(item.desc || ''); + return `${stars}${updated}${name}${desc}`; + }).join(''); + trendingBody.innerHTML = rows; + } + + async function loadTrending() { + if (!trendingBody) return; + try { + const res = await fetch('/trending_poc.json', { cache: 'no-store' }); + if (!res.ok) { + throw new Error(`Failed to load trending (${res.status})`); + } + const data = await res.json(); + const items = Array.isArray(data) ? data : (data.items || []); + renderTrending(items); + } catch (err) { + console.warn(err.message); + } + } + function doSearch(event) { const val = searchValue.value.trim(); if (val !== '') { controls.displayResults(results, resultsTableHideable); + if (trendingSection) { + trendingSection.style.display = 'none'; + } currentSet = window.controls.doSearch(val, window.dataset || []); if (currentSet.length < totalLimit) { @@ -176,6 +221,9 @@ document.addEventListener('DOMContentLoaded', () => { controls.hideResults(results, resultsTableHideable); window.controls.setColor(colorUpdate, 'no-search'); noResults.style.display = 'none'; + if (trendingSection) { + trendingSection.style.display = ''; + } } if (event.type === 'submit') { @@ -219,4 +267,6 @@ document.addEventListener('DOMContentLoaded', () => { clearTimeout(debounceTimer); debounceTimer = setTimeout(() => doSearch(event), 200); }); + + loadTrending(); }); diff --git a/docs/search/index.html b/docs/search/index.html deleted file mode 100644 index 00acacfbf7..0000000000 --- a/docs/search/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - CVE PoC Hub - Search - - - -
-
-

Find exploit writeups and PoCs instantly

-

Search by CVE id, vendor, product, or keyword.

-
- Linked PoCs - MITRE CVE pages - Vendor / product filters - Supports negative terms (e.g. -windows) -
-
- -
- -
-
- - - - diff --git a/docs/trending_poc.json b/docs/trending_poc.json new file mode 100644 index 0000000000..fc92af9481 --- /dev/null +++ b/docs/trending_poc.json @@ -0,0 +1,4 @@ +{ + "generated": "2025-12-18T00:00:00Z", + "items": [] +} diff --git a/scripts/README.md b/scripts/README.md index f61d89e7b8..484c63fbbb 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -7,7 +7,7 @@ pip install -r requirements.txt python scripts/fetch_kev.py python scripts/fetch_epss.py python scripts/build_site.py -python scripts/build_all.py # new PoC discovery + scoring pipeline +python scripts/build_all.py ``` Outputs land in `docs/` and JSON under `docs/api/v1/`. Snapshots live in `docs/api/v1/snapshots/` (last 14 days) and diffs under `docs/api/v1/diffs/`. diff --git a/scripts/build_all.py b/scripts/build_all.py index e952bc71cc..f6105ef673 100644 --- a/scripts/build_all.py +++ b/scripts/build_all.py @@ -19,7 +19,6 @@ from pipeline_outputs import ( write_top, ) from poc_pipeline import PoCPipeline, build_scope, persist_evidence -from site_renderer import SiteRenderer from utils import API_DIR, DOCS_DIR, load_json @@ -106,10 +105,7 @@ def main(argv: List[str] | None = None) -> int: prune_old_snapshots() prune_old_diffs() - renderer = SiteRenderer(results=results, index_payload=index_payload, top_payload=top_payload, diff_payload=diff_payload) - renderer.build() - - print(f"Generated site under {DOCS_DIR}") + print(f"Wrote pipeline outputs under {DOCS_DIR}") print(f"Wrote latest snapshot to {snapshot_path}") return 0 diff --git a/scripts/build_site.py b/scripts/build_site.py index 853aedc34d..594af3a1de 100644 --- a/scripts/build_site.py +++ b/scripts/build_site.py @@ -1,31 +1,22 @@ from __future__ import annotations import argparse -from datetime import timedelta -from pathlib import Path +import json import re -from typing import Dict, Tuple +from datetime import datetime, timezone +from pathlib import Path +from typing import Dict, List, Optional +from urllib.parse import urlparse from jinja2 import Environment, FileSystemLoader, select_autoescape -from utils import ( - API_DIR, - DOCS_DIR, - TEMPLATES_DIR, - ensure_dirs, - load_json, - load_poc_index, - parse_trending_from_readme, - save_json, -) +from utils import DOCS_DIR, TEMPLATES_DIR, ensure_dirs, load_blacklist, parse_trending_from_readme, is_blacklisted_repo -from build_joined import build_joined, write_api_outputs -from build_diffs import build_diff, prune_snapshots - -KEV_DATA = DOCS_DIR.parent / "data" / "kev.json" -EPSS_DATA = DOCS_DIR.parent / "data" / "epss.json" -README_PATH = DOCS_DIR.parent / "README.md" -TRENDING_WINDOW = timedelta(days=4) +ROOT = DOCS_DIR.parent +README_PATH = ROOT / "README.md" +CVE_OUTPUT = DOCS_DIR / "CVE_list.json" +REMOVED_OUTPUT = DOCS_DIR / "CVE_blacklist_removed.json" +TRENDING_OUTPUT = DOCS_DIR / "trending_poc.json" def build_env() -> Environment: @@ -42,160 +33,200 @@ def render(env: Environment, template_name: str, context: Dict, output_path: Pat output_path.write_text(html, encoding="utf-8") -def load_joined() -> Dict: - kev = load_json(KEV_DATA, default={}) - epss = load_json(EPSS_DATA, default={}) - poc_index = load_poc_index() - payload = build_joined(kev, epss, poc_index) - write_api_outputs(payload) - return payload +def normalise_block(text: str) -> str: + text = text.replace("\r\n", "\n") + text = re.sub(r"\n{2,}", "\n", text.strip()) + lines = [line.lstrip("- ").rstrip() for line in text.split("\n")] + return "\n".join(line for line in lines if line) -def write_snapshot(joined: Dict) -> Path: - snapshot_path = API_DIR / "snapshots" / f"{joined['generated']}.json" - ensure_dirs(snapshot_path.parent) - save_json(snapshot_path, joined) - return snapshot_path +def parse_sections(content: str) -> Dict[str, str]: + sections: Dict[str, str] = {} + current_header: Optional[str] = None + buffer: List[str] = [] + + for line in content.splitlines(): + header = line.strip() + if header.startswith("### ") or header.startswith("#### "): + if current_header is not None: + sections[current_header] = "\n".join(buffer).strip() + current_header = header + buffer = [] + else: + buffer.append(line) + + if current_header is not None: + sections[current_header] = "\n".join(buffer).strip() + + return sections -def _parse_year(row: dict) -> int | None: +def repo_from_url(url: str) -> str: try: - return int(row.get("year")) - except (TypeError, ValueError): - return None + parsed = urlparse(url) + host = (parsed.netloc or "").lower() + if host and "github" not in host: + return "" + path = parsed.path or url + except Exception: + path = url + parts = path.strip("/").split("/") + if len(parts) >= 2: + return parts[1].lower() + return (parts[-1] if parts else "").lower() -def _age_from_label(label: str) -> timedelta | None: - text = (label or "").strip().lower() - if text == "just now": - return timedelta() - match = re.match(r"(?P\d+)\s+(?Pminute|minutes|hour|hours|day|days)\s+ago", text) - if not match: - return None - value = int(match.group("value")) - unit = match.group("unit") - if unit.startswith("minute"): - return timedelta(minutes=value) - if unit.startswith("hour"): - return timedelta(hours=value) - return timedelta(days=value) - - -def _is_current_year_name(name: str, year: int) -> bool: - return bool(re.search(rf"cve-{year}-\d+", name or "", re.IGNORECASE)) - - -def select_trending(readme_rows: list[dict]) -> list[dict]: - """Pick up to 20 entries from the newest year table, filtered to last 4 days, with descriptions, matching the current year.""" - if not readme_rows: - return [] - - years = [yr for yr in (_parse_year(row) for row in readme_rows) if yr is not None] - if not years: - return [] - - latest_year = max(years) - filtered: list[tuple[dict, timedelta]] = [] - for row in readme_rows: - if _parse_year(row) != latest_year: +def is_blacklisted(url: str, blacklist: List[str]) -> bool: + repo = repo_from_url(url) + if not repo: + return False + for entry in blacklist: + slug = entry.lower() + if not slug: continue - if not _is_current_year_name(row.get("name", ""), latest_year): + if slug.endswith("*"): + if repo.startswith(slug[:-1]): + return True + elif repo == slug: + return True + return False + + +def collect_links(block: str, *, blacklist: Optional[List[str]] = None, removed: Optional[List[str]] = None) -> List[str]: + links: List[str] = [] + blacklist = blacklist or [] + if removed is None: + removed = [] + for raw in block.splitlines(): + entry = raw.strip() + if not entry or "No PoCs" in entry: continue - if not (row.get("desc") or "").strip(): + if entry.startswith("- "): + entry = entry[2:].strip() + if not entry: continue - age = _age_from_label(row.get("updated", "")) - if age is None or age > TRENDING_WINDOW: + if is_blacklisted(entry, blacklist): + removed.append(entry) continue - filtered.append((row, age)) - - # Sort by freshness then stars - filtered.sort(key=lambda pair: (pair[1], -int(pair[0].get("stars") or 0))) - - selected: list[dict] = [] - for row, _age in filtered[:20]: - try: - stars = int(row.get("stars") or 0) - except (TypeError, ValueError): - stars = 0 - selected.append( - { - "stars": stars, - "updated": (row.get("updated") or "").strip(), - "name": (row.get("name") or "").strip(), - "url": (row.get("url") or "").strip(), - "desc": (row.get("desc") or "").strip(), - "year": latest_year, - } - ) - return selected + if entry not in links: + links.append(entry) + return links -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"] +def build_cve_list(blacklist: List[str]) -> Dict[str, object]: + cve_entries = [] + removed_by_cve: Dict[str, List[str]] = {} + removed_seen: set[str] = set() - trending_raw = parse_trending_from_readme(README_PATH) - trending = select_trending(trending_raw) - recent_kev = (diff or {}).get("new_kev_entries") or [] - metrics = { - "kev_total": len(data["kev_enriched"]), - "high_epss_count": len(joined["high_epss"]), - "recent_kev_count": len(recent_kev), + for md_path in sorted(ROOT.glob("[12][0-9][0-9][0-9]/CVE-*.md")): + content = md_path.read_text(encoding="utf-8") + sections = parse_sections(content) + description = normalise_block(sections.get("### Description", "")) + removed_links: List[str] = [] + references = collect_links(sections.get("#### Reference", ""), blacklist=blacklist, removed=removed_links) + github_links = collect_links(sections.get("#### Github", ""), blacklist=blacklist, removed=removed_links) + + poc_entries: List[str] = [] + seen = set() + for link in references + github_links: + if link not in seen: + poc_entries.append(link) + seen.add(link) + + cve_id = md_path.stem + if removed_links: + removed_by_cve[cve_id] = sorted(set(removed_links)) + removed_seen.update(removed_links) + + if not poc_entries: + continue + + cve_entries.append({ + "cve": cve_id, + "desc": description, + "poc": poc_entries, + }) + + return { + "entries": cve_entries, + "removed": { + "removed": sorted(removed_seen), + "by_cve": removed_by_cve, + }, } - if html_mode in {"summary", "all"}: - common_ctx = {"generated": joined["generated"], "metrics": metrics, "recent_kev": recent_kev} - 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 == "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") +def build_trending(blacklist: List[str]) -> List[Dict[str, object]]: + rows = parse_trending_from_readme(README_PATH) + if not rows: + return [] - 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") + by_year: Dict[int, List[Dict[str, object]]] = {} + for row in rows: + year_text = row.get("year") or "" + if not str(year_text).isdigit(): + continue + year = int(year_text) + url = (row.get("url") or "").strip() + if url and is_blacklisted_repo(url, blacklist): + continue + stars_text = str(row.get("stars") or "").strip() + stars = int(re.sub(r"\D", "", stars_text) or 0) + item = { + "year": year, + "stars": stars, + "updated": (row.get("updated") or "").strip(), + "name": (row.get("name") or "").strip(), + "url": url, + "desc": (row.get("desc") or "").strip(), + } + by_year.setdefault(year, []).append(item) + + if not by_year: + return [] + + current_year = datetime.now(timezone.utc).year + target_year = current_year if current_year in by_year else max(by_year) + return by_year.get(target_year, []) + + +def write_json(path: Path, data, *, indent: Optional[int] = None) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + with path.open("w", encoding="utf-8") as handle: + json.dump(data, handle, ensure_ascii=False, indent=indent) def main() -> int: - parser = argparse.ArgumentParser(description="Build static site and JSON") + parser = argparse.ArgumentParser(description="Build CVE PoC site") parser.add_argument( "--html-mode", choices=["none", "summary", "all"], - default="none", - help="Render no HTML, summary pages only, or all pages including per-CVE.", + default="summary", + help="Render HTML or skip it.", ) args = parser.parse_args() - ensure_dirs(DOCS_DIR, DOCS_DIR / "kev", DOCS_DIR / "epss", DOCS_DIR / "diffs") + ensure_dirs(DOCS_DIR) + blacklist = load_blacklist() - data = load_joined() - # snapshot + diff before rendering so dashboard can show it - snapshot_path = write_snapshot(data["joined"]) - snapshots = sorted((API_DIR / "snapshots").glob("*.json")) - diff, target = build_diff( - snapshots, - kev_full=data["kev_enriched"], - threshold=0.05, - max_movers=50, - recent_days=30, + cve_payload = build_cve_list(blacklist) + write_json(CVE_OUTPUT, cve_payload["entries"]) + write_json(REMOVED_OUTPUT, cve_payload["removed"], indent=2) + + trending_items = build_trending(blacklist) + write_json( + TRENDING_OUTPUT, + { + "generated": datetime.now(timezone.utc).isoformat(), + "items": trending_items, + }, + indent=2, ) - prune_snapshots(snapshots, lookback_days=14) if args.html_mode != "none": env = build_env() - build_pages(env, data, diff, html_mode=args.html_mode) + render(env, "index.html", {"trending": trending_items}, DOCS_DIR / "index.html") - # build daily diff after snapshot is written print("Site generated under docs/") return 0 diff --git a/scripts/site_renderer.py b/scripts/site_renderer.py deleted file mode 100644 index 447cbd1971..0000000000 --- a/scripts/site_renderer.py +++ /dev/null @@ -1,99 +0,0 @@ -from __future__ import annotations - -from pathlib import Path -from typing import Dict, List - -from jinja2 import Environment, FileSystemLoader, select_autoescape - -from utils import DOCS_DIR, TEMPLATES_DIR, ensure_dirs - - -def build_env() -> Environment: - loader = FileSystemLoader(str(TEMPLATES_DIR)) - env = Environment(loader=loader, autoescape=select_autoescape(["html", "xml"])) - env.trim_blocks = True - env.lstrip_blocks = True - return env - - -class SiteRenderer: - def __init__( - self, - *, - results: List[Dict], - index_payload: Dict, - top_payload: Dict, - diff_payload: Dict | None = None, - ) -> None: - self.results = [] - for result in results: - visible = [p for p in result.get("pocs", []) if p.get("confidence_tier") in {"high", "medium"}] - if not visible: - visible = result.get("pocs", []) - self.results.append({**result, "visible_pocs": visible}) - self.index_payload = index_payload - self.top_payload = top_payload - self.diff_payload = diff_payload or {} - self.env = build_env() - ensure_dirs( - DOCS_DIR, - DOCS_DIR / "pocs", - DOCS_DIR / "cve", - DOCS_DIR / "diffs", - DOCS_DIR / "assets", - ) - - def render(self, template_name: str, context: Dict, target: Path) -> None: - html = self.env.get_template(template_name).render(**context) - target.parent.mkdir(parents=True, exist_ok=True) - target.write_text(html, encoding="utf-8") - - def build(self) -> None: - generated = self.index_payload.get("generated") - summary = { - "generated": generated, - "total_cves": len(self.index_payload.get("items", [])), - "total_pocs": sum(item.get("poc_count", 0) for item in self.index_payload.get("items", [])), - "high_total": sum(item.get("high_confidence", 0) for item in self.index_payload.get("items", [])), - "medium_total": sum(item.get("medium_confidence", 0) for item in self.index_payload.get("items", [])), - } - self.render( - "pipeline_index.html", - { - "summary": summary, - "top": self.top_payload.get("items", [])[:25], - "diff": self.diff_payload or {}, - }, - DOCS_DIR / "index.html", - ) - - self.render( - "pipeline_pocs.html", - { - "generated": generated, - "index": self.index_payload.get("items", []), - "top": self.top_payload.get("items", [])[:100], - }, - DOCS_DIR / "pocs" / "index.html", - ) - - for result in self.results: - self.render( - "pipeline_cve.html", - {"cve": result, "generated": generated}, - DOCS_DIR / "cve" / f"{result['cve_id']}.html", - ) - - if self.diff_payload: - diff_date = self.diff_payload.get("generated") - self.render( - "pipeline_diff.html", - {"diff": self.diff_payload, "generated": generated}, - DOCS_DIR / "diffs" / "index.html", - ) - if diff_date: - self.render( - "pipeline_diff.html", - {"diff": self.diff_payload, "generated": generated}, - DOCS_DIR / "diffs" / f"{diff_date}.html", - ) diff --git a/templates/base.html b/templates/base.html index a54799dfa8..033b06ad5c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -6,28 +6,11 @@ {{ title or 'CVE PoC Hub' }} - -
{% block content %}{% endblock %}
-
-
- Fast CVE triage without the noise. - GitHub repo -
-
{% block extra_scripts %}{% endblock %} diff --git a/templates/cve.html b/templates/cve.html deleted file mode 100644 index 82059711b0..0000000000 --- a/templates/cve.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends "base.html" %} -{% block content %} -

{{ cve.cve }}

-

{{ cve.description or 'No description available.' }}

-
- {% if cve.kev %}In KEV{% else %}Not in KEV{% endif %} - {% if cve.epss is not none %}EPSS {{ '%.3f'|format(cve.epss) }} ({{ '%2.0f'|format((cve.percentile or 0)*100) }}th){% endif %} - {% if cve.kev and cve.kev.due_date %}Due {{ cve.kev.due_date }}{% endif %} -
- -{% if cve.poc_links %} -

Proof of Concepts

-
    - {% for link in cve.poc_links %} -
  • {{ link }}
  • - {% endfor %} -
-{% endif %} - -{% if cve.kev %} -

KEV Details

-
    -
  • Date added: {{ cve.kev.date_added }}
  • - {% if cve.kev.due_date %}
  • Due date: {{ cve.kev.due_date }}
  • {% endif %} -
  • Required action: {{ cve.kev.required_action }}
  • - {% if cve.kev.notes %}
  • Notes: {{ cve.kev.notes }}
  • {% endif %} -
-{% endif %} -{% endblock %} diff --git a/templates/diffs.html b/templates/diffs.html deleted file mode 100644 index 60868116c2..0000000000 --- a/templates/diffs.html +++ /dev/null @@ -1,27 +0,0 @@ -{% extends "base.html" %} -{% block content %} -
-
-

New KEV entries

- Only the recent additions -
-
- - - - {% for row in recent_kev %} - - - - - - - - - - {% else %}{% endfor %} - -
CVEVendorProductEPSSPercentileDate AddedDue
{{ row.cve }}{{ row.vendor }}{{ row.product }}{{ '%.3f'|format(row.epss or 0) }}{{ '%2.0f'|format((row.percentile or 0)*100) }}th{{ row.date_added }}{{ row.due_date or '—' }}
No fresh KEV entries in the last 30 days.
-
-
-{% endblock %} diff --git a/templates/epss.html b/templates/epss.html deleted file mode 100644 index f86adaf5cf..0000000000 --- a/templates/epss.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends "base.html" %} -{% block content %} -
-
-

EPSS highlights

- High-probability CVEs that are not in KEV. -
- -
- - - - {% for row in epss %} - - - - - - - - {% endfor %} - -
CVEEPSSPercentilePoCsSummary
{{ row.cve }}{{ '%.3f'|format(row.epss or 0) }}{{ '%2.0f'|format((row.percentile or 0)*100) }}th{{ row.poc_count }}{{ row.summary or 'No public description yet.' }}
-
-
-{% endblock %} diff --git a/templates/index.html b/templates/index.html index cae01de93c..a12098c700 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,15 +1,14 @@ {% extends "base.html" %} {% set body_class = "color-no-search" %} {% block content %} -
-
-

Search by CVE id, vendor, product, or keyword.

-
- Linked PoCs - MITRE CVE pages - Vendor / product filters - Supports negative terms (e.g. -windows) -
+
+

Find exploit writeups and PoCs instantly

+

Search by CVE id, vendor, product, or keyword.

+
+ Linked PoCs + MITRE CVE pages + Vendor / product filters + Supports negative terms (e.g. -windows)
@@ -17,7 +16,6 @@
-
-
-

Trending PoCs

- Current year, updated in the last 4 days -
+
+

Latest PoC examples

@@ -51,32 +46,7 @@ {% else %} - - {% endfor %} - -
StarsUpdatedNameDescription
{{ row.desc }}
No recent PoCs.
-
-
- -
-
-

High EPSS not in KEV

- Sorted by score -
-
- - - - {% for row in data.high_epss %} - - - - - - - - {% else %} - + {% endfor %}
CVEEPSSPercentilePoCsSummary
{{ row.cve }}{{ '%.3f'|format(row.epss or 0) }}{{ '%2.0f'|format((row.percentile or 0)*100) }}th{{ row.poc_count }}{{ row.summary or 'No public description yet.' }}
No high-EPSS items outside KEV today.
No recent PoCs.
diff --git a/templates/kev.html b/templates/kev.html deleted file mode 100644 index acfaac217c..0000000000 --- a/templates/kev.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends "base.html" %} -{% block content %} -
-
-

KEV catalog

- Filter by CVE, vendor, or product. -
- -
- - - - - - {% for row in kev %} - - - - - - - - - - {% endfor %} - -
CVEVendorProductEPSSPercentileDate AddedDue
{{ row.cve }}{{ row.vendor }}{{ row.product }}{{ '%.3f'|format(row.epss or 0) }}{{ '%2.0f'|format((row.percentile or 0)*100) }}th{{ row.date_added }}{{ row.due_date or '—' }}
-
-
-{% endblock %} diff --git a/templates/pipeline_base.html b/templates/pipeline_base.html deleted file mode 100644 index 3489f0104b..0000000000 --- a/templates/pipeline_base.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - {% block title %}CVE PoC Hub{% endblock %} - - - -
- -
-
- {% block content %}{% endblock %} -
-
- -
- - - diff --git a/templates/pipeline_cve.html b/templates/pipeline_cve.html deleted file mode 100644 index 11accf1dbe..0000000000 --- a/templates/pipeline_cve.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "pipeline_base.html" %} -{% block title %}{{ cve.cve_id }} PoCs{% endblock %} -{% block content %} -
-
-
-

CVE record

-

{{ cve.cve_id }}

-

Last updated {{ cve.last_updated }}

-
- JSON -
- -
- {% for poc in cve.visible_pocs %} -
- -
- {{ poc.confidence_tier|capitalize }} ({{ poc.confidence_score|round(1) }}) - {% if poc.primary_language %}{{ poc.primary_language }}{% endif %} - {% if poc.stars %}{{ poc.stars }}★{% endif %} - {% if poc.is_fork %}Fork{% endif %} -
-
- {% if poc.pushed_at %}Updated {{ poc.pushed_at }} · {% endif %} - {% if poc.archived %}Archived{% endif %} - {% if poc.parent_repo_url %}Parent: {{ poc.parent_repo_url }}{% endif %} -
-
- {% for topic in poc.topics %}{{ topic }}{% endfor %} -
-
-
Matches
-
    - {% for match in poc.matches %} -
  • {{ match.match_type }} {{ match.path }}
  • - {% endfor %} -
-
-
- {% else %} -

No PoCs found yet for {{ cve.cve_id }}.

- {% endfor %} -
-
-{% endblock %} diff --git a/templates/pipeline_diff.html b/templates/pipeline_diff.html deleted file mode 100644 index 60d3802944..0000000000 --- a/templates/pipeline_diff.html +++ /dev/null @@ -1,72 +0,0 @@ -{% extends "pipeline_base.html" %} -{% block title %}Diff {{ diff.generated or generated }}{% endblock %} -{% block content %} -
-
-
-

Daily delta

-

Diff for {{ diff.generated }}

-
- JSON -
- -
-
-

New high-confidence PoCs

- -
-
-

Promoted to high

- -
-
- -
-
-

Demoted or removed

-
    - {% for item in diff.demoted_or_removed %} -
  • - - {{ item.cve_id }} - {{ item.repo_full_name }} -
  • - {% else %} -
  • No removals.
  • - {% endfor %} -
-
-
-

Dead links (optional checks)

-
    - {% for item in diff.dead_links %} -
  • offline {{ item.url }}
  • - {% else %} -
  • Link checks skipped or none failed.
  • - {% endfor %} -
-
-
-
-{% endblock %} diff --git a/templates/pipeline_index.html b/templates/pipeline_index.html deleted file mode 100644 index d0ec05234c..0000000000 --- a/templates/pipeline_index.html +++ /dev/null @@ -1,69 +0,0 @@ -{% extends "pipeline_base.html" %} -{% block title %}CVE PoC Radar{% endblock %} -{% block content %} -
-
-

Daily GitHub sweep

-

CVE PoC Goldmine

-

Incremental discovery, scoring, and diffing for public exploit PoCs. High-confidence hits surface first; low-signal noise stays out of the spotlight.

- -
-
-
-
High confidence
-
{{ summary.high_total }}
-
-
-
Medium confidence
-
{{ summary.medium_total }}
-
-
-
Tracked CVEs
-
{{ summary.total_cves }}
-
-
Generated {{ summary.generated }}
-
-
- -
-
-

Top PoCs right now

- JSON -
-
- {% for poc in top %} -
- -
- {{ poc.tier|capitalize }} - {{ poc.score|round(1) }} pts - {% if poc.stars %}{{ poc.stars }}★{% endif %} - {% if poc.primary_language %}{{ poc.primary_language }}{% endif %} -
- -
- {% else %} -

No PoCs available yet.

- {% endfor %} -
-
- -
-
-

Latest diff

- Diffs -
- {% if diff and diff.new_high_conf_pocs %} -
- {% for item in diff.new_high_conf_pocs %} - + {{ item.cve_id }} / {{ item.repo_full_name }} - {% endfor %} -
- {% else %} -

No new high-confidence PoCs in the latest run.

- {% endif %} -
-{% endblock %} diff --git a/templates/pipeline_pocs.html b/templates/pipeline_pocs.html deleted file mode 100644 index 23ec5c3190..0000000000 --- a/templates/pipeline_pocs.html +++ /dev/null @@ -1,47 +0,0 @@ -{% extends "pipeline_base.html" %} -{% block title %}PoC Explorer{% endblock %} -{% block content %} -
-
-

PoC Explorer

-
Search across the pre-built index JSON. Client-side results stay small and fast.
-
- -
-

Type to search recent CVEs. Results stream in from /api/v1/index.json.

-
-
- -
-
-

Latest high + medium

-
Server-side snapshot
-
-
- - - - - - - - - - - - {% for item in index %} - - - - - - - - {% else %} - - {% endfor %} - -
CVEHighMediumLanguagesMax score
{{ item.cve_id }}{{ item.high_confidence }}{{ item.medium_confidence }}{% for lang in item.top_languages %}{{ lang }}{% else %}{% endfor %}{{ item.max_score|round(1) }}
No entries available.
-
-
-{% endblock %} diff --git a/templates/vendor.html b/templates/vendor.html deleted file mode 100644 index 062eb4764e..0000000000 --- a/templates/vendor.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "base.html" %} -{% block content %} -

{{ vendor.vendor }}

-

{{ cves|length }} CVEs

-
- - - - {% for detail in cves %} - - - - - - - {% endfor %} - -
CVEEPSSKEVPoCs
{{ detail.cve }}{% if detail.epss is not none %}{{ '%.3f'|format(detail.epss) }}{% else %}—{% endif %}{{ 'Yes' if detail.kev else 'No' }}{{ detail.poc_count }}
-
-{% endblock %}