diff --git a/.github/getTrending.py b/.github/getTrending.py
index 3fca31f89f..944b617e32 100644
--- a/.github/getTrending.py
+++ b/.github/getTrending.py
@@ -1,9 +1,11 @@
#!/usr/bin/env python3
-"""Regenerate the Trending PoCs table in README.md.
+"""Regenerate the Trending PoCs tables in README.md.
-- Only consider repositories whose names contain the current year's CVE pattern (e.g., CVE-2025-1234).
+- Consider the latest 4 years (current year and previous 3).
+- Require repository name to contain a CVE for that year (e.g., CVE-2025-1234).
+- Require a non-empty description (we only want actual PoCs, not empty shells).
- Restrict to repositories updated in the last 4 days.
-- Sort by most recently updated, then stars, and emit up to 20 rows.
+- Sort by most recently updated, then stars, and emit up to 20 rows per year.
"""
from __future__ import annotations
@@ -18,6 +20,7 @@ import requests
WINDOW_DAYS = 4
MAX_ROWS = 20
+YEARS_BACK = 4
class Repo(TypedDict):
@@ -50,8 +53,8 @@ def time_ago(updated_at: str, now: datetime) -> str:
return "just now"
-def fetch_trending(current_year: int, cutoff: datetime) -> List[Repo]:
- query = f"CVE-{current_year} in:name stars:>2 pushed:>={cutoff.date().isoformat()} archived:false"
+def fetch_trending(year: int, cutoff: datetime) -> List[Repo]:
+ query = f"CVE-{year} in:name stars:>2 pushed:>={cutoff.date().isoformat()} archived:false"
url = "https://api.github.com/search/repositories"
params = {
"q": query,
@@ -63,12 +66,13 @@ def fetch_trending(current_year: int, cutoff: datetime) -> List[Repo]:
resp = requests.get(url, params=params, headers=github_headers(), timeout=30)
resp.raise_for_status()
items: Iterable[Repo] = resp.json().get("items", [])
- pattern = re.compile(rf"cve-{current_year}-\d+", re.IGNORECASE)
+ pattern = re.compile(rf"cve-{year}-\d+", re.IGNORECASE)
filtered: List[Repo] = []
for item in items:
name = item.get("name", "")
updated_at = item.get("updated_at")
- if not updated_at or not pattern.search(name or ""):
+ description = (item.get("description") or "").strip()
+ if not updated_at or not pattern.search(name or "") or not description:
continue
updated_dt = datetime.strptime(updated_at, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
if updated_dt < cutoff:
@@ -94,20 +98,21 @@ def main() -> None:
cutoff = datetime.now(timezone.utc) - timedelta(days=WINDOW_DAYS)
now = datetime.now(timezone.utc)
- repos = fetch_trending(current_year, cutoff)
-
output: List[str] = ['
Recently updated Proof-of-Concepts
']
- output.append(f"\n\n## {current_year}\n")
- output.append(f"### Updated in the last {WINDOW_DAYS} days (up to {MAX_ROWS} repos)\n")
- output.append("| Stars | Updated | Name | Description |")
- output.append("| --- | --- | --- | --- |")
- if repos:
- output.extend(build_rows(repos, now))
- else:
- output.append("| 0⭐ | — | No recent CVE PoCs | No repositories matched the filters. |")
+
+ for year in range(current_year, current_year - YEARS_BACK, -1):
+ repos = fetch_trending(year, cutoff)
+ output.append(f"\n\n## {year}\n")
+ output.append(f"### Updated in the last {WINDOW_DAYS} days (up to {MAX_ROWS} repos)\n")
+ output.append("| Stars | Updated | Name | Description |")
+ output.append("| --- | --- | --- | --- |")
+ if repos:
+ output.extend(build_rows(repos, now))
+ else:
+ output.append("| 0⭐ | — | No recent CVE PoCs | No repositories matched the filters. |")
Path("README.md").write_text("\n".join(output), encoding="utf-8")
- print(f"Wrote {len(repos)} rows for {current_year}")
+ print(f"Wrote tables for {YEARS_BACK} years ending {current_year}")
if __name__ == "__main__":
diff --git a/README.md b/README.md
index 9ef59a29a1..7fcf72e104 100644
--- a/README.md
+++ b/README.md
@@ -10,8 +10,34 @@
| 360⭐ | 2 hours ago | [Next.js-RSC-RCE-Scanner-CVE-2025-66478](https://github.com/Malayke/Next.js-RSC-RCE-Scanner-CVE-2025-66478) | A command-line scanner for batch detection of Next.js application versions and determining if they are affected by CVE-2025-66478 vulnerability. |
| 4⭐ | 13 hours ago | [CVE-2025-66478-POC](https://github.com/wangxso/CVE-2025-66478-POC) | CVE-2025-66478 Proof of Concept |
| 4⭐ | 22 hours ago | [CVE-2025-65318-and-CVE-2025-65319](https://github.com/bbaboha/CVE-2025-65318-and-CVE-2025-65319) | Insecure attachment handling when using Canary Mail or Blue mail |
-| 6⭐ | 1 day ago | [CVE-2025-55184-POC-Expolit](https://github.com/cybertechajju/CVE-2025-55184-POC-Expolit) | |
| 78⭐ | 1 day ago | [Blackash-CVE-2025-55182](https://github.com/Ashwesker/Blackash-CVE-2025-55182) | CVE-2025-55182 |
| 3⭐ | 1 day ago | [CVE-2025-54100](https://github.com/ThemeHackers/CVE-2025-54100) | CVE-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. |
| 17⭐ | 1 day ago | [CVE-2025-55182](https://github.com/ThemeHackers/CVE-2025-55182) | a 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. |
-| 5⭐ | 3 days ago | [CVE-2025-55182-golang-PoC](https://github.com/keklick1337/CVE-2025-55182-golang-PoC) | CVE-2025-55182 React Server Components RCE - Go PoC |
\ No newline at end of file
+| 5⭐ | 3 days ago | [CVE-2025-55182-golang-PoC](https://github.com/keklick1337/CVE-2025-55182-golang-PoC) | CVE-2025-55182 React Server Components RCE - Go PoC |
+
+
+## 2024
+
+### Updated in the last 4 days (up to 20 repos)
+
+| Stars | Updated | Name | Description |
+| --- | --- | --- | --- |
+| 0⭐ | — | No recent CVE PoCs | No repositories matched the filters. |
+
+
+## 2023
+
+### Updated in the last 4 days (up to 20 repos)
+
+| Stars | Updated | Name | Description |
+| --- | --- | --- | --- |
+| 4⭐ | 3 days ago | [F5-BIG-IP-SmuggleShell-CVE-2023-46747-Exploit](https://github.com/Razzlemouse/F5-BIG-IP-SmuggleShell-CVE-2023-46747-Exploit) | #F5-BIG-IP-CVE-2023-46747-Exploit – Unauthenticated RCE Python exploit & Nuclei template by Raguraman ✓ Automated TCP reverse shell (LHOST/LPORT) ✓ Tested on affected BIG-IP 13.x–17.x ⚠️ Authorized pentesting only |
+
+
+## 2022
+
+### Updated in the last 4 days (up to 20 repos)
+
+| Stars | Updated | Name | Description |
+| --- | --- | --- | --- |
+| 0⭐ | — | No recent CVE PoCs | No repositories matched the filters. |
\ No newline at end of file
diff --git a/docs/index.html b/docs/index.html
index 4da3ba7f39..d6f55505ca 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -92,12 +92,6 @@
CVE-2025-55182 |
a 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. |
-
- | 6 |
- 1 day ago |
- CVE-2025-55184-POC-Expolit |
- |
-
| 3 |
1 day ago |
diff --git a/scripts/build_site.py b/scripts/build_site.py
index ad84c195e3..853aedc34d 100644
--- a/scripts/build_site.py
+++ b/scripts/build_site.py
@@ -86,7 +86,7 @@ def _is_current_year_name(name: str, year: int) -> bool:
def select_trending(readme_rows: list[dict]) -> list[dict]:
- """Pick up to 20 entries from the newest year table, filtered to last 4 days and matching the current year."""
+ """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 []
@@ -101,6 +101,8 @@ def select_trending(readme_rows: list[dict]) -> list[dict]:
continue
if not _is_current_year_name(row.get("name", ""), latest_year):
continue
+ if not (row.get("desc") or "").strip():
+ continue
age = _age_from_label(row.get("updated", ""))
if age is None or age > TRENDING_WINDOW:
continue