Commit Graph
43 Commits
Author SHA1 Message Date
0xMarcio 7a33d182ac Prefer positive CVSS assessments 2026-09-01 23:56:04 +02:00
0xMarcio 8fe2bf2d04 Index verified advisory PoCs and expand CVSS sources 2026-09-01 23:17:04 +02:00
0xMarcio dcf4068b7a Deduplicate published sources and improve filters 2026-09-01 22:08:20 +02:00
0xMarcio 74a9e53c2c Prefer named CVEs during discovery 2026-09-01 19:33:38 +02:00
0xMarcio 3f72a21d2d Refine GitHub PoC classification 2026-09-01 19:24:05 +02:00
0xMarcio 81017c9871 Expand CVE PoC coverage and metadata 2026-09-01 19:01:07 +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 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
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 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 2b6547ef29 Badge known-exploited CVEs in the repository itself
KEV reached the site three days ago but nothing in the markdown said a
vulnerability was under active attack, and the repository is what most
people actually read. 1,595 entries now carry a red CISA KEV shield beside
their product and vulnerability badges, marked for ransomware use where
CISA records it.

update_cves writes the badge on entries it creates, and the weekly audit
reconciles the whole set against the refreshed catalogue, so an entry CISA
adds gains the badge and one it withdraws loses it. Re-running the sync is
a no-op.
2026-08-31 04:02:59 +02:00
0xMarcio 8c739f44e5 Reskin to GitHub Primer dark
Every colour is now a Primer dark_default token. The header band, its four
capability pills and the heading above the trending table are gone, so the
search field is the first thing on the page and the switcher labels its own
table. Rows tighten to 10px, descriptions clamp to two lines, and the PoC
list loses its box for a hairline rule.

Blue is the only thing you can click. Amber means 500 stars or more and red
means known-exploited, and nothing else carries a hue: the star glyph is
dimmed at every value so the column reads as numbers rather than symbols.

The handoff's placeholder wanted an em dash. It reads "Search CVE, vendor,
product or keyword, exclude with -windows" with the middot the count line
already uses, and the six em dashes I had left in code comments are gone
too.
2026-08-31 04:00:54 +02:00
0xMarcio 42e055b60b Sweep every reference link for rot
The first full pass over all 60,039 reference URLs: 1,566 answer 404 or
410, which removes 2,663 links from 2,419 entries and 2,445 lines from
references.txt. Anything that timed out, refused a HEAD or answered 403
kept its link.

The weekly job takes it from here on a five-week cycle, so this only had to
be paid once.
2026-08-31 03:09:10 +02:00
0xMarcio b6d3f380ca Stop paying twice for an unreachable host
A timeout kept the link either way, but the checker still followed a failed
HEAD with a GET to the same dead host, so every unreachable URL cost two
full timeouts. Return on the first network failure and drop the timeout to
eight seconds: a measured 1,500 references went from roughly three URLs a
second to fifteen.

That pass removed 98 links across 86 inventory lines, and the weekly budget
rises to 12,000 references, which sweeps the corpus every five weeks.
2026-08-31 01:45:23 +02:00
0xMarcio 66a4f41227 Check reference links for rot, not just repositories
The audit only ever asked GitHub about repositories, leaving 60,112
reference URLs unchecked since the corpus was inherited. Sampling put hard
404s at 4%, and one host accounts for a fifth of that on its own: CIS
retired the OVAL Repository, so all 942 links to it are permanently gone
and are removed in the next commit.

The rest is diffuse, so it needs sweeping rather than a rule. Check an
eighth of the URLs each week alongside the repositories, ordered
round-robin by host so a slice does not arrive at one server as a burst.
Only a 404 or 410 removes a link: a timeout, a refused HEAD or a 403 keeps
it, and update_cves already applies the same test to references it
discovers, so this holds inherited links to the standard new ones meet.
2026-08-31 00:27:34 +02:00
0xMarcio 6822fdbfbc Fix three ways the index misread its own data
An advisory copied from a GitHub Security Advisory opens with "### Impact"
or "### Summary". The section parser treated any heading as a boundary, so
those descriptions ended themselves and reached the site empty. Only the
four headings an entry actually uses end a section now, and leading heading
markers are stripped when the text is rendered.

A trailing slash made exploit-db.com/exploits/41034 and .../41034/ two
different links, which put 53 duplicate rows in front of readers.

github.com also serves attachments and advisories, and 103 of those were
being parsed as owner/repo -- rendering "user-attachments / files" with an
empty star column instead of the PoC archive they point to.
2026-08-31 00:22:44 +02:00
0xMarcio 1aa51fa852 Mark the CVEs attackers are actually using
CISA publishes a catalogue of vulnerabilities observed being exploited in
the wild, and 1,111 of its 1,685 entries are CVEs this index already holds
PoCs for. That is the one fact a reader most wants before opening an
exploit, and it was nowhere on the page.

The weekly audit stores the catalogue, the build trims it to the CVEs the
index carries, and a result row shows a KEV chip -- with the ransomware
flag where CISA records one, which covers 352 of them. 37 KB served.

A failed fetch keeps the stored catalogue rather than dropping the badge
off every entry. The chip reuses the header pill's treatment: the palette
still spends green on things you can click and amber on star counts only.
2026-08-31 00:13:01 +02:00
0xMarcio 58c70b93ab Recognise a proof of concept written in another language
The PoC vocabulary was English-only, so a repository describing itself as
"漏洞利用" — an exploit — read as evidence that it was not one. Chinese is
the second language of this corpus by a wide margin, and the same gap
covered Spanish, Portuguese, French, Russian, Japanese and Korean.

NON_POC_RE also vetoed "prueba", which is the proof in "prueba de
concepto", inverting the signal for Spanish repositories entirely.

On the 600-repository discovery sample this admits two more genuine PoCs
and nothing else.
2026-08-30 23:24:11 +02:00
0xMarcio 576b0e4735 Collect stars and last push during the weekly audit
The audit already asks GitHub about every linked repository, so the same
query can carry back a star count and a last-push date for free. Results go
to repo_meta.json, which lets a search result say which of two hundred
linked PoCs is worth opening.

2.1 MB for 45,008 repositories, refreshed weekly.
2026-08-30 21:53:20 +02:00
0xMarcio 5452bc8353 Report when a PoC repository last shipped code
The trending table sorted and displayed updated_at, which also moves when a
repository merely gains a star, so a four-month-old exploit was claiming it
had been updated three hours ago. Record pushed_at and created_at and let
the page decide: last commit for the age it shows, repository age for the
trending rank.

The job now writes trending.json alongside the README table, so the site
reads the data instead of regex-parsing markdown the same job generated.
2026-08-30 21:53:19 +02:00
0xMarcio 85fe2b3ad4 Retire the abandoned second pipeline
Ten modules totalling 2,206 lines, reachable from no workflow and no live
script, alongside 18 MB of github-all.txt and references-all.txt that
nothing reads and 400 KB of stale api/v1 output that shipped in every
Pages artifact. scripts/README.md documented this as the build process.

utils.py existed for one caller and duplicated functions build_site.py
already had, so it folds into it. Nothing imports a third-party package
any more, and requirements.txt goes with it.
2026-08-30 21:09:37 +02:00
0xMarcio 6d65ae36bb Audit PoC links against GitHub weekly
Sampling the corpus put 17% of the repositories it links to behind a 404,
so readers were following links to repositories that no longer exist. The
previous audit script was 630 lines, never wired to anything, and kept its
state under a gitignored directory.

Replace it with a check that batches repository lookups through GraphQL
and removes a link only when GitHub answers NOT_FOUND for it, so a
throttle or a network error can never drop one. A quarter of the corpus
runs each week, which stays inside the token's hourly budget and sweeps
everything within the month.
2026-08-30 21:09:35 +02:00
0xMarcio 0aa40a5f49 Reject CVE ids that are a truncation of the one a repo is about
A README caption in maniakh/CVE-2026-31431---Copy-Fail-PoC reads
"Copy Fail (CVE-2026-3143)", one digit short. That still parses as a
valid identifier, and the guard meant to catch it was satisfied by the
repo's generic exploit.py, so the PoC was filed against an unrelated
WordPress advisory. CVE-2026-8222 (Open5GS) collected a GiveWP lab the
same way. Drop an id from the same year that a longer mentioned id
extends, unless the repository name deliberately carries both.

Underscores are word characters, so the id regex matched neither half of
a name like CVE-2022-4174_CVE-2022-41742; read the separator-normalised
name too. Over 600 live candidates that recovers two real PoCs the gap
was hiding, Keycloak_CVE-2026-18963_PoC and CVE-2026-42945_NginxRift.
2026-08-30 17:38:58 +02:00
0xMarcio f9fc5ae28d Stop tracking generated site data
Pages builds from the workflow artifact, so the committed CVE_list.json
was never served while adding a fresh 53 MB blob to history every day.
Generate it during the Pages build instead and drop the duplicate
generator; scripts/build_site.py is now the only thing that writes it.

The jinja2 templates re-rendered a trending table that logic.js replaces
on load, so the page shell goes back to being a plain static file and the
Pages build no longer installs anything. Shallow-clone the sync job too:
it never reads git history, and the three-day lookback already recovers
a skipped day.
2026-08-30 16:59:31 +02:00
0xMarcio b1ac17daf9 Widen PoC discovery and fix the empty version badge
A repository dedicated to one CVE that calls itself a PoC and ships code
was still vetoed when its description happened to contain a generic word
like writeup, patched or detector. Check the description alongside the
name for PoC intent; pure scanners that never claim to be a PoC stay out.
Measured on 600 live candidates: 15 repositories gained, none lost.

Fall back to n/a for missing versions, matching the product and
vulnerability badges instead of rendering an empty shields.io chip.
2026-08-30 16:59:13 +02:00
0xMarcio c8fbbc40b2 Clean and verify CVE PoC sources 2026-08-29 04:29:03 +02:00
0xMarcio a62cda8ec8 Automate CVE PoC ingestion 2026-08-29 00:21:06 +02:00
0xMarcio 5c78e585a1 Simplify site to search + trending 2025-12-18 07:13:08 +01:00
0xMarcio 0afef5597e Restore multi-year trending PoCs with 4-day filter 2025-12-17 21:14:24 +01:00
0xMarcio 722d7261ba Filter trending PoCs to current-year updates 2025-12-17 21:06:33 +01:00
0xMarcio 23be2e0751 Fix trending PoCs rendering and simplify frontend 2025-12-17 20:54:34 +01:00
0xMarcio 0bd6c7ceda Align trending PoCs and filter to recent data 2025-12-17 20:24:46 +01:00
0xMarcio da14307c37 Filter to PoC-backed CVEs and fix trending PoCs 2025-12-17 19:39:59 +01:00
0xMarcio 0f18fc5736 Refresh KEV and EPSS pages for cleaner signal 2025-12-17 18:24:55 +01:00
0xMarcio 1ae3d7e711 Fix search layout and add dynamic CVE pages 2025-12-17 17:38:30 +01:00
0xMarcio 1f0cd8e78b Add PoC pipeline with blacklist filtering and Pages build 2025-12-17 15:53:37 +01:00
0xMarcio aac323de9b Add KEV/EPSS static site generator 2025-12-17 13:59:41 +01:00
0xMarcio 0c3e517733 Automate CVE sync and daily PoC refresh 2025-09-19 00:48:01 +02:00