Rebrand to PoC Index and move to pocindex.io

The site called itself three different things: CVE PoC Hub in the title, CVE
Radar in the h1 and the social metadata, and cve on GitHub. Google had no
consistent site name to settle on, so none of the mentions compounded. CVE
Radar was taken anyway, by SOCRadar's free tool and by cveradar.com.

Every user-facing name and URL now comes from scripts/brand.py, so the next
move is one edit rather than a sweep through the tree.

Also repairs the parts of the site a crawler could not use:

- robots.txt and sitemap.xml were both 404. scripts/build_seo.py writes them,
  wired into the Pages job. trending_poc.json, kev.json and stats.json stay
  crawlable because the first paint needs them; the five bulk payloads are
  disallowed, which is 13.2 MB per crawl spent on data no crawler queries.
- Search state lives in ?q= now. Results were unlinkable, so nobody could cite
  one and there was no route for a SearchAction to declare. replaceState
  rather than pushState, so typing does not bury the back button.
- A WebSite JSON-LD block carries the name Google prints as the site name.
- The footer carries the MITRE trademark notice.
This commit is contained in:
0xMarcio committed 2026-09-02 03:36:22 +02:00
1 parent e58a5a26cc
commit 31da22381c
22 files changed
+270 -75

No files matched your search

+20 -19
View File
@@ -45,6 +45,7 @@ USER_AGENT = "0xMarcio-cve-trending"
ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
sys.path.insert(0, os.path.join(ROOT, "scripts"))
from brand import BRAND, SITE
from update_cves import load_blacklist, qualifying_repo_cves
README = os.path.join(ROOT, "README.md")
@@ -506,11 +507,11 @@ def refresh_count_header() -> int:
badges = {
"CVEs with PoCs": pill(
"CVEs with PoCs", f"{counts['with_pocs']:,}", "2f81f7",
"https://cve.codepwn.win/",
f"{SITE}/",
),
"known exploited": pill(
"known exploited", f"{counts['kev']:,}", "f85149",
"https://cve.codepwn.win/",
f"{SITE}/",
),
}
badge_replacements = 0
@@ -536,7 +537,7 @@ def header(stamp: str, synced: str) -> list[str]:
because GitHub proxies README images and would otherwise serve a stale copy
of a file that is redrawn whenever the index moves."""
counts = figures()
home = "https://cve.codepwn.win/"
home = f"{SITE}/"
badges = [
pill("last sync", synced, "2f81f7", f"https://github.com/{SLUG}/commits/main"),
live_pill("actions/workflow/status/" + SLUG + "/hot_cves.yml", "CI", "2f81f7",
@@ -551,11 +552,11 @@ def header(stamp: str, synced: str) -> list[str]:
return [
'<div align="center">',
"",
f'<a href="{home}"><img src="{HERO_URL}?v={count_stamp(counts)}" alt="CVE Radar" width="100%"></a>',
f'<a href="{home}"><img src="{HERO_URL}?v={count_stamp(counts)}" alt="{BRAND}" width="100%"></a>',
"",
"&nbsp;".join(badges),
"",
f'<a href="{home}"><img src="{SEARCH_CTA_URL}" alt="Search CVE Radar" width="100%"></a>',
f'<a href="{home}"><img src="{SEARCH_CTA_URL}" alt="Search {BRAND}" width="100%"></a>',
"",
"</div>",
"",
@@ -570,25 +571,25 @@ Every file is plain JSON on the CDN. No key, no rate limit.
```bash
# everything the index knows about one CVE
curl -s https://cve.codepwn.win/CVE_list.json \\
curl -s @SITE@/CVE_list.json \\
| jq '.[] | select(.cve == "CVE-2021-44228") | {cve, poc: (.poc | length), nuclei, msf, edb, vulhub, collections}'
# every published CVSS assessment plus vetted advisory links
curl -s https://cve.codepwn.win/cve_metadata.json | jq '."CVE-2021-44228"'
curl -s @SITE@/cve_metadata.json | jq '."CVE-2021-44228"'
# likelihood of exploitation in the next 30 days
curl -s https://cve.codepwn.win/epss.json | jq '."CVE-2021-44228"'
curl -s @SITE@/epss.json | jq '."CVE-2021-44228"'
# stars and last push for one PoC repository; repository keys are lowercased
curl -s https://cve.codepwn.win/repo_meta.json | jq '."sfewer-r7/cve-2026-55040"'
curl -s @SITE@/repo_meta.json | jq '."sfewer-r7/cve-2026-55040"'
```
What CISA says is being exploited, that also has a PoC here, ranked by how
likely each is to be used next:
```bash
curl -s https://cve.codepwn.win/kev.json -o kev.json
curl -s https://cve.codepwn.win/epss.json -o epss.json
curl -s @SITE@/kev.json -o kev.json
curl -s @SITE@/epss.json -o epss.json
jq -n --slurpfile kev kev.json --slurpfile epss epss.json \\
'[$kev[0] | keys[] | select($epss[0][.]) | {cve: ., epss: $epss[0][.][0]}]
| sort_by(-.epss) | .[:10]'
@@ -596,13 +597,13 @@ jq -n --slurpfile kev kev.json --slurpfile epss epss.json \\
| Endpoint | Holds |
| --- | --- |
| [`CVE_list.json`](https://cve.codepwn.win/CVE_list.json) | Every CVE with a linked PoC, its description and its `poc`, `nuclei`, `msf`, `edb`, `vulhub` and `collections` links |
| [`cve_metadata.json`](https://cve.codepwn.win/cve_metadata.json) | NVD CVSS v2.0, v3.0, v3.1 and v4.0 assessments with vectors and vetted advisory links |
| [`epss.json`](https://cve.codepwn.win/epss.json) | Exploitation probability and percentile, for nearly every CVE indexed |
| [`nuclei.json`](https://cve.codepwn.win/nuclei.json) | Template metadata for the CVEs covered by a runnable Nuclei check |
| [`kev.json`](https://cve.codepwn.win/kev.json) | CISA known exploited, keyed by CVE id |
| [`repo_meta.json`](https://cve.codepwn.win/repo_meta.json) | Stars and last push date per PoC repository, keys lowercased |
| [`trending_poc.json`](https://cve.codepwn.win/trending_poc.json) | Trending repositories plus index totals |
| [`CVE_list.json`](@SITE@/CVE_list.json) | Every CVE with a linked PoC, its description and its `poc`, `nuclei`, `msf`, `edb`, `vulhub` and `collections` links |
| [`cve_metadata.json`](@SITE@/cve_metadata.json) | NVD CVSS v2.0, v3.0, v3.1 and v4.0 assessments with vectors and vetted advisory links |
| [`epss.json`](@SITE@/epss.json) | Exploitation probability and percentile, for nearly every CVE indexed |
| [`nuclei.json`](@SITE@/nuclei.json) | Template metadata for the CVEs covered by a runnable Nuclei check |
| [`kev.json`](@SITE@/kev.json) | CISA known exploited, keyed by CVE id |
| [`repo_meta.json`](@SITE@/repo_meta.json) | Stars and last push date per PoC repository, keys lowercased |
| [`trending_poc.json`](@SITE@/trending_poc.json) | Trending repositories plus index totals |
| [`cves/2026/CVE-2026-68138.md`](cves/2026/CVE-2026-68138.md) | Markdown copy of one CVE, one directory per year |
CVSS rows are `[version, score, severity, vector, source, assessment type]`.
@@ -641,7 +642,7 @@ Advisory rows are `[URL, NVD reference tags]`.
Missing PoC, wrong link, dead repository: open an issue with the CVE id and the
repository URL.
"""
""".replace("@SITE@", SITE)
def main() -> int:
+16 -11
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Render the CVE Radar hero banner and social card as self-contained SVG.
"""Render the PoC Index hero banner and social card as self-contained SVG.
Both cards are plain SVG with no external font, image or stylesheet reference:
GitHub proxies README images through camo, which fetches the file on its own and
@@ -11,12 +11,17 @@ from __future__ import annotations
import importlib.util
import json
import os
import sys
from urllib import request
ROOT = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir))
BUILD_SITE = os.path.join(ROOT, "scripts", "build_site.py")
LIVE_STATS = "https://cve.codepwn.win/trending_poc.json"
LIVE_KEV = "https://cve.codepwn.win/kev.json"
sys.path.insert(0, os.path.join(ROOT, "scripts"))
from brand import BRAND, SITE, SUBTITLE, host
LIVE_STATS = f"{SITE}/trending_poc.json"
LIVE_KEV = f"{SITE}/kev.json"
HERO = os.path.join(ROOT, "docs", "hero.svg")
SOCIAL = os.path.join(ROOT, "docs", "social-card.svg")
STATS = os.path.join(ROOT, "docs", "stats.json")
@@ -122,16 +127,16 @@ def hero(counts: dict) -> str:
)
)
return f"""<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="180" viewBox="0 0 1200 180"
role="img" aria-label="CVE Radar, {group(counts['with_pocs'])} CVEs with public proof-of-concept exploits">
role="img" aria-label="{BRAND}, {group(counts['with_pocs'])} CVEs with public proof-of-concept exploits">
<clipPath id="card"><rect x="1" y="1" width="1198" height="178" rx="12"/></clipPath>
<rect x="0.5" y="0.5" width="1199" height="179" rx="12" fill="{CANVAS}" stroke="{BORDER}"/>
<g clip-path="url(#card)" opacity="0.6">{sweep(1090, 90, 160, 0.3)}</g>
<text x="56" y="70" font-family="{MONO}" font-size="44" font-weight="700"
fill="{FG}" letter-spacing="2">CVE RADAR</text>
fill="{FG}" letter-spacing="2">{BRAND}</text>
<text x="56" y="104" font-family="{MONO}" font-size="15" fill="{MUTED}">
Public proof-of-concept exploits, indexed by CVE.</text>
<text x="56" y="132" font-family="{MONO}" font-size="15" fill="{ACCENT}">cve.codepwn.win</text>
{SUBTITLE}</text>
<text x="56" y="132" font-family="{MONO}" font-size="15" fill="{ACCENT}">{host()}</text>
{blocks}
</svg>
@@ -149,22 +154,22 @@ def social(counts: dict) -> str:
)
)
return f"""<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="640" viewBox="0 0 1280 640"
role="img" aria-label="CVE Radar">
role="img" aria-label="{BRAND}">
<clipPath id="card"><rect x="56" y="56" width="1168" height="528" rx="16"/></clipPath>
<rect width="1280" height="640" fill="{CANVAS}"/>
<g clip-path="url(#card)" opacity="0.6">{sweep(1000, 300, 220, 0.26)}</g>
<rect x="56" y="56" width="1168" height="528" rx="16" fill="none" stroke="{BORDER}"/>
<text x="96" y="215" font-family="{MONO}" font-size="76" font-weight="700"
fill="{FG}" letter-spacing="3">CVE RADAR</text>
fill="{FG}" letter-spacing="3">{BRAND}</text>
<text x="96" y="272" font-family="{MONO}" font-size="24" fill="{MUTED}">
Public proof-of-concept exploits, indexed by CVE.</text>
{SUBTITLE}</text>
<rect x="96" y="344" width="1088" height="1" fill="{BORDER}"/>
{blocks}
<text x="96" y="532" font-family="{MONO}" font-size="22" fill="{ACCENT}"
letter-spacing="1">cve.codepwn.win</text>
letter-spacing="1">{host()}</text>
</svg>
"""
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add --all -- \
.github/link_audit_state.json \
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add --all -- \
README.md \
index/trending.json \
+4 -1
View File
@@ -1,4 +1,4 @@
name: Build & Deploy CVE Radar
name: Build & Deploy PoC Index
on:
schedule:
@@ -32,6 +32,9 @@ jobs:
- name: Build site data
run: python3 scripts/build_site.py
- name: Build robots.txt and sitemap.xml
run: python3 scripts/build_seo.py
- name: Verify published counts
run: |
python3 .github/hero.py
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add --all -- \
README.md \
docs/hero.svg \
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add --all -- \
.github/cve_sync_state.json \
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add --all -- \
README.md \
docs/hero.svg \
+1 -1
View File
@@ -57,7 +57,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add -- \
README.md \
cves/ \
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add --all -- \
README.md \
docs/hero.svg \
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
- name: Check for changes and commit
run: |
git config user.name 'CVE-BOT'
git config user.email '[email protected]'
git config user.email '[email protected]'
git add --all -- \
README.md \
docs/hero.svg \