Commit Graph
3172 Commits
Author SHA1 Message Date
0xMarcio 31da22381c 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.
2026-09-02 03:36:22 +02:00
CVE-BOT e58a5a26cc Trending CVEs update 2026-09-01 23:17 🤖 2026-09-01 23:17:01 +00:00
0xMarcio fb2029b3ea Pin README search asset 2026-09-02 01:09:22 +02:00
0xMarcio 8dec6181e8 Refine README search strip 2026-09-02 01:07:28 +02:00
0xMarcio 0748d77eee Add README search call to action 2026-09-02 01:05:49 +02:00
0xMarcio aad1789a71 Keep published counts synchronized 2026-09-02 00:54:09 +02:00
0xMarcio 55279dcfe5 Improve trending year coverage 2026-09-02 00:44:21 +02:00
0xMarcio 7a33d182ac Prefer positive CVSS assessments 2026-09-01 23:56:04 +02:00
0xMarcio 95b818930a Remove unscored severity filter 2026-09-01 23:26:48 +02:00
CVE-BOT 0f3caaa80c Sync CVE metadata 2026-09-01 2026-09-01 21:21:30 +00:00
0xMarcio 8fe2bf2d04 Index verified advisory PoCs and expand CVSS sources 2026-09-01 23:17:04 +02:00
CVE-BOT 597a0da838 Trending CVEs update 2026-09-01 20:58 🤖 2026-09-01 20:58:48 +00:00
0xMarcio dcf4068b7a Deduplicate published sources and improve filters 2026-09-01 22:08:20 +02:00
0xMarcio e534a2d0d9 Avoid duplicate Pages deployments 2026-09-01 20:01:14 +02:00
CVE-BOT d6221a7081 Add PoC repositories from upstream collection 2026-09-01 2026-09-01 17:58:11 +00:00
CVE-BOT 768ffb1c40 Trending CVEs update 2026-09-01 17:49 🤖 2026-09-01 17:49:58 +00:00
CVE-BOT ec0fae9788 Trending CVEs update 2026-09-01 17:43 🤖 2026-09-01 17:43:44 +00:00
CVE-BOT d992851f33 Update CVE PoCs 2026-09-01 2026-09-01 17:41:09 +00:00
0xMarcio 74a9e53c2c Prefer named CVEs during discovery 2026-09-01 19:33:38 +02:00
CVE-BOT 4bf4d58446 Update CVE PoCs 2026-09-01 2026-09-01 17:31:21 +00:00
0xMarcio 3f72a21d2d Refine GitHub PoC classification 2026-09-01 19:24:05 +02:00
CVE-BOT f45e320a38 Update CVE PoCs 2026-09-01 2026-09-01 17:16:04 +00:00
0xMarcio 796d813803 Persist CVE discovery state 2026-09-01 19:08:30 +02:00
0xMarcio 81017c9871 Expand CVE PoC coverage and metadata 2026-09-01 19:01:07 +02:00
CVE-BOT d006786a98 Trending CVEs update 2026-09-01 14:07 🤖 2026-09-01 14:07:19 +00:00
CVE-BOT 3f4626884b Trending CVEs update 2026-09-01 13:52 🤖 2026-09-01 13:52:06 +00:00
0xMarcio f140e13160 Repair the README pipeline after the move
Moving the data files into index/ left three references behind in .github,
and the hourly job has been failing to stage its own output since. The
README has been advertising 104,016 CVEs with PoCs while the site served
89,125, and every KEV marker had dropped out of its table because the
catalogue was being read from a path that no longer exists.

Figures come from the same count build_site publishes, so the badges, the
hero card and the site cannot disagree again.
2026-09-01 15:50:08 +02:00
0xMarcio 2821985dd9 Reach the PoCs published before the search window opens
Discovery asks GitHub for repositories pushed in the last three days, so a
proof of concept written for a 2019 CVE in 2021 is unreachable however long
the job runs. nomi-sec/PoC-in-GitHub has collected them daily since 1999.

It collects without filtering, which is how this index inherited its junk
the first time, so nothing arrives trusted: every candidate goes through
qualifying_repo_cves, the same gate a repository found by search must pass.
Of 6,945 candidates the gate rejected 4,110 and accepted 2,835, adding
links to 1,528 entries that had none or had fewer.

Vulhub joins the curated archives beside ExploitDB and Metasploit. It is
241 entries, and each one is a docker-compose file and reproduction steps
rather than a description of a flaw.

Candidates are judged again every week rather than remembered as rejected:
an empty shell in March is often a working exploit by June.
2026-09-01 15:21:53 +02:00
0xMarcio bafbb8d4d6 Scan five years of CVEs for new PoCs, not two
Discovery only looked at the current year and the one before it, so a PoC
published this week for a 2023 CVE was never found. Exploits for older
vulnerabilities keep appearing, and the daily run has budget to spare: the
window is still three days, so the cost is five sets of search terms instead
of two against the same short window.
2026-09-01 14:43:39 +02:00
0xMarcio a7449da61b Move the year directories out of the repository root
Twenty-eight year folders sat above the README, so anyone opening the
repository scrolled past 1999 through 2026 before reaching a word about what
it is. The entries move to cves/ and the files the pipeline reads and writes
move to index/, which leaves the root at README, LICENSE and five
directories.

Nothing about the data changes. Every script takes its two roots from the
same place, and all five syncs report zero writes against the moved tree,
which is what a correct repoint looks like.
2026-09-01 14:43:38 +02:00
0xMarcio 7d6671d56a Drop links that only announce a patch
An Oracle Critical Patch Update page, an Ubuntu Security Notice and a CERT
vulnerability note all say the same thing: a fix exists. None of them shows
anyone how the flaw works, so none belongs in a list of proofs of concept.
26,070 of them were in there, inherited from a workflow that kept every
reference a CVE record carried.

advisory_hosts.txt names the destinations, matched as host plus leading
path, and update_cves consults it so nothing of the shape returns.
securityfocus.com/bid joins them for a different reason: the service is
retired and every deep link now lands on a search box.

The list is deliberately short. Packet Storm, Full Disclosure, openwall,
bugzilla, hackerone and the exploit archives all carry working code often
enough that a host-wide rule would delete real proofs of concept, so they
stay and are judged link by link.
2026-09-01 14:34:27 +02:00
0xMarcio 1b87e9669d Only index a nuclei template that exercises the bug
Wordfence templates do not exploit anything. They fetch a plugin's
readme.txt, read the version string and report that a vulnerable release is
installed: 80,706 of their 81,526 templates are that and nothing else, and
not one sends a payload. Yesterday's widening filed 35,383 of them as proofs
of concept, which is a claim the files do not support.

Judge the template rather than the repository it came from. A template whose
every request reads readme.txt, style.css or a changelog, and which never
sends a body or a payload, is a version probe and is skipped wherever it
comes from. That keeps the 382 real templates Wordfence does publish and
drops the same shape out of the community sets, which were re-hosting them.

39,973 templated CVEs becomes 4,929 and 19,504 entries give up a nuclei
section they should never have been given. The index returns to 104,184
CVEs with PoCs from an inflated 117,373.
2026-09-01 14:11:21 +02:00
0xMarcio e5a1c5633f Take nuclei templates from more than one repository
ProjectDiscovery templates what the whole industry cares about, which leaves
most of the WordPress plugin CVEs that dominate this index with no runnable
check at all. Wordfence publishes one for nearly all of them and updates
daily; a second community set fills a further gap.

The filename pattern was the barrier. ProjectDiscovery names a template for
its CVE and nothing else, so an exact match worked; Wordfence appends the
plugin slug and an advisory uuid, and all 36,529 of its templates were being
skipped by a regex anchored to the end of the name.

4,420 CVEs templated becomes 39,973, of which 19,945 land on entries this
index carries. Ratings follow the links, so CVEs carrying a severity and
CVSS go from 3,952 to 23,897. ProjectDiscovery keeps precedence where it has
a template; the rest are read only for CVEs it does not cover.
2026-09-01 13:50:39 +02:00
0xMarcio a150d3d1b9 Give every entry its publication dates
The design asked for published and modified in the result column and the
frontend has been rendering them since the reskin, against a field nothing
supplied. Seeded from the CVE Program's daily release: 154,160 of 154,166
CVEs, so coverage on the indexed set is total.

The 590 MB archive is a one-off. Every record the delta log hands the daily
sync afterwards already carries its own dates, so update_cves keeps the file
current from work it was doing anyway.

Costs 0.86 MB gzipped on the index.
2026-09-01 13:44:47 +02:00
0xMarcio a2c376e77d Stop filing Metasploit scanners as proofs of concept
A module's CVE list comes from its own declared references, so an exploit
that chains two flaws should be linked under both. A scanner is different:
"SSL/TLS Version Detection" cites BEAST, RC4, POODLE and Logjam because it
reports on them, and CVE-2014-3566 was carrying it as exploit code. So were
"SSH Username Enumeration" and "JBoss Vulnerability Scanner".

Keep auxiliary and post modules only where they name a single CVE, which is
the shape of an auxiliary module that is itself the exploit; exploit modules
keep every CVE they declare. 3,542 links become 3,339, 86 entries lose a
Metasploit section entirely and 51 lose part of one.

Metasploit also ships CVE-1012-5358 for CVE-2012-5358. The regex accepted
it; an impossible year is now rejected before it can invent a 1012/
directory.
2026-09-01 13:44:46 +02:00
CVE-BOT d874588866 Trending CVEs update 2026-09-01 08:34 🤖 2026-09-01 08:34:22 +00:00
CVE-BOT 9d4f3d8739 Update CVE PoCs 2026-09-01 2026-09-01 07:52:05 +00:00
0xMarcio 164b2a6fad Rewrite the data examples as commands that actually run
The first one never worked. It selected CVE-2026-75604, an id lifted from a
trending repository name without checking the CVE was in the index, and it is
not, so the command downloaded 48 MB to print nothing. The repo_meta example
was worse: it returned null every time, because those keys are lowercased and
the example was not.

Every command in the README has now been run against the deployed files, and
the block is regenerated from the same source, so what is printed is what was
tested. The examples also answer questions worth asking rather than restating
the schema: what the index knows about one CVE across all four sources, how
bad it is and how likely it is to be used, and what CISA says is being
exploited that also has a PoC here, ranked by exploitation probability.

The endpoint table gains the two new files and notes the size of the big one
and the key casing that caused this. A sources table replaces guessing where
any of it came from.
2026-09-01 06:01:55 +02:00
0xMarcio fc827abb8f Fill blank descriptions in the year tables too
Five rows on the last run were an empty cell. The landed lane already fell
back to the CVE's own summary; these CVEs are older and always in the index,
so the same lookup costs nothing and no row ships blank now.
2026-09-01 05:47:03 +02:00
CVE-BOT 188f0646c5 Trending CVEs update 2026-09-01 03:42 🤖 2026-09-01 03:42:54 +00:00
0xMarcio 749424a8a1 Find day-one PoCs and check they carry code before linking them
The just landed lane still ran the language filter, and a repository published
this morning does not have one: GitHub has not classified it yet. Measured on
a three day window, filtering on language dropped 17 of 47 CVE-2026 repositories,
and the ones it dropped were the newest. Both filters are gone from this lane.

Dropping them lets through what they were incidentally keeping out, so the
check is now direct: every candidate has its root tree read, and a repository
holding nothing but a README and a licence is rejected as a write-up rather
than an exploit. Three were turned away on this run, and the lane went from
ten rows to seventeen candidates carrying real code.

Rows also stop shipping blank. A repository a day old often has no description,
so the CVE's own summary stands in, taken from the index or, for a CVE too new
to have been synced yet, from NVD directly. Every row on this run has one,
where four were empty before.
2026-09-01 05:41:05 +02:00
0xMarcio 84da5a5fc6 Index ExploitDB and Metasploit, score everything with EPSS, and stop hiding new PoCs
Four gaps, measured against the index before any of this was written.

ExploitDB and Metasploit are folded in the way nuclei templates were. ExploitDB
covers 25,066 CVEs and adds 30,327 links across 17,237 entries; Metasploit
covers 3,178 and adds 3,520 across 2,550. Together with the templates the index
goes from 101,809 CVEs carrying a PoC to 103,945. Neither archive skews recent,
which is why nuclei went first, but both are the difference between an old CVE
having nothing and having something that runs. Each keeps its own section and
its own field, and each leads the list ahead of the repositories: a module, an
entry and a template all run as they stand, without reading somebody's code.

EPSS now covers the index rather than the 4,274 CVEs a template happened to
rate. FIRST's daily feed scores 103,783 of 103,945, so a result can say how
likely a flaw is to be exploited in the next thirty days, not only that code
exists for it. It is fetched during the site build and never tracked here: a
daily rescore of 366,000 rows would be nothing but churn.

The trending tables also stop hiding what they exist to show. The star floor
excluded 1,059 of the 1,312 2026 PoC repositories pushed this quarter, and a
repository published this morning has no stars, so the newest row on the front
page was six days old. A separate lane drops the floor entirely and pays for it
with a ten day window, a cap of ten rows, and the same paperwork check the rest
of the table uses. The newest row is now hours old.
2026-09-01 05:24:39 +02:00
0xMarcio ff11c84652 Stage the nuclei sync with a pathspec git accepts
git would not expand [12][0-9][0-9][0-9] as a pathspec, so the job did its
work and then died on the commit. Everything it touches is already tracked
apart from nuclei.json, so stage tracked changes and name that one file.
2026-09-01 05:12:57 +02:00
0xMarcio 35cb1e6962 Index nuclei templates as PoCs and take their ratings with them
A nuclei template is a runnable check for one CVE, which makes it a proof of
concept whether or not anyone published a repository for it. Measured against
the index: 3,952 CVEs gain a template link and 858 of those had no PoC at all,
584 of the additions falling in 2024 or later. That last figure is the point.
ExploitDB carries more CVEs overall and Metasploit is better weaponised, but
both skew historical; nuclei is where coverage of a recent CVE actually shows
up first.

Templates also carry the ratings the entries never had. Severity, CVSS with
its vector, EPSS with its percentile and CWE now sit in nuclei.json for the
site to read: 4,193 of 4,418 templates state a CVSS score and 4,274 an EPSS
score. A result can finally say how bad a flaw is and how likely it is to be
used, rather than only that somebody wrote code for it.

Templates are kept in their own section and their own field. They are not
somebody's repository and should not be ranked, starred or credited as one,
but they do lead the PoC list, being the one link that runs as it stands.

The index files are also revalidated rather than reused from cache. They are
rebuilt hourly and a returning visitor was holding whatever it downloaded
first, which cost a stale index here until the copy was thrown away by hand.
2026-09-01 05:11:31 +02:00
0xMarcio fca6754b6f Send stray keystrokes to the search field
Landing on the page and typing did nothing, so the first thing anyone tries
was lost and the field had to be clicked first. It is focused on load on
viewports wide enough to imply a keyboard, and typing anywhere else moves
focus there.

Focus moves during keydown rather than on the character itself, so the
keystroke that triggered it still lands in the field: typing gitea from
anywhere on the page searches for gitea, not itea. A lone slash focuses
without typing itself, and escape clears the field and steps back out.
2026-09-01 04:54:53 +02:00
0xMarcio a6be0d9794 Ignore assistant tooling
None of it is part of the project and a stray config committed once tends to
stay. The repository already had no such files tracked; this keeps it that way.
2026-09-01 04:51:07 +02:00
0xMarcio de770d6c6f Bring the site up to the README and fix the unreadable text
The page and the README had drifted into looking like two projects. The site
now opens on the same card the README banner draws, built as markup rather
than a second copy of the image, so it fills itself from the index totals the
page already loads and cannot go stale.

Contrast was the real problem. --neutral sat at 4.12:1 against the canvas,
under the 4.5 floor, and it carried the search placeholder, the star glyph and
every separator; descriptions were rendered in the muted token at 6.15:1 while
doing the work of body copy. Descriptions move to a subtle token at 12.26:1,
muted and neutral both come up, and links go to the brighter accent at 7.49:1.
The column headers were 9.5px mono under a tenth of an em of tracking, which
no contrast ratio was going to rescue.

Known-exploited CVEs are marked in the trending table too, not only inside a
result, since which row to read first is the one thing the table could not
say. The README swaps the fire emoji for the same KEV pill, served from the
repository so every flagged row points at one cached file.

The search field no longer repeats the totals now that the hero carries them,
and keeps its slot for the match timing.
2026-09-01 04:46:30 +02:00
0xMarcio b3b204bec9 Label the workflow badge CI
"Sweep" was internal vocabulary. Nobody reading the repository knows it means
the hourly job.
2026-09-01 04:32:22 +02:00
CVE-BOT cf3ea1e7b7 Trending CVEs update 2026-09-01 02:29 🤖 2026-09-01 02:29:52 +00:00
0xMarcio 2ed7386028 Give the README a banner and cut it back to the useful parts
The README opened on a bare heading and five year tables, said nothing about
what the project is, and never linked the site. Anyone landing on the repo had
to guess. It now leads with a generated banner carrying the live index totals,
a badge row, and tables trimmed to what fits a table cell.

hero.py draws the banner and the social card as self-contained SVG, since
GitHub proxies README images and drops anything the file has to fetch for
itself. It counts the corpus through build_site's own parser rather than a
second guess at what counts as a PoC, so the banner cannot drift from the site
header, and leaves the figures in docs/stats.json for the README build to
quote. If the count fails it falls back to the deployed site and, failing
that, writes nothing at all: a banner reading zero is worse than yesterday's.

Badges describing the index are baked in at build time so they always match
the banner and cannot degrade to "resource not found"; the two that describe
live GitHub state carry a stamp that defeats the image proxy cache.

The sweep now runs hourly instead of every six hours. It takes under two
minutes and the repository shows up in "recently updated" far more often.

Also adds the OpenGraph tags the site never had, so a shared link renders a
card instead of a bare URL.
2026-09-01 04:28:33 +02:00