Your personal vulnerability intelligence radar — fork, configure, and go!
| 📊 CVEs Tracked | 🚨 Critical | 🔥 Exploit Intel | |
|---|---|---|---|
| 2179 | 45 | 167 | 173 |
Last scanned: 2026-02-06 15:40 UTC
|
Matching your watchlist |
PoC + In your stack = 🔥 |
CISA confirmed active |
From PatchThis feeds |
📈 What do these metrics mean?
| Metric | Description | Why It Matters |
|---|---|---|
| CVEs Tracked | Total CVEs matching your watchlist.yaml vendors/products |
Your attack surface visibility |
| Critical | CVEs with known exploit code AND in your watchlist | Immediate patching priority |
| In KEV | Listed in CISA's Known Exploited Vulnerabilities catalog | Active exploitation in the wild |
| Exploit Intel | Has PoC/weaponized code (from PatchThis) | Threat actors have working exploits |
💡 Tip: These metrics auto-update every hour when the ETL workflow runs in your fork.
VulnRadar is a lightweight, GitHub-native vulnerability intelligence tool that:
- 📥 Downloads the latest CVE data from
CVEProject/cvelistV5and NVD data feeds - 🎯 Filters CVEs against your tech stack via
watchlist.yaml - 🔥 Enriches with CISA KEV, EPSS, NVD, and PatchThis intelligence
- 📊 Generates a beautiful Markdown report viewable directly in GitHub
- 🚨 Creates GitHub Issues for critical findings (with escalation comments!)
- 🔔 Sends Discord/Slack/Teams notifications (optional)
- 📋 Integrates with GitHub Projects v2 for Kanban workflows (optional)
- 🎭 Includes demo mode for conference presentations
No API keys. No external services. Just fork and go.
Click the Fork button at the top right of this page.
⚠️ Important: GitHub automatically disables workflows on forked repositories for security reasons. You must manually enable them.
Go to your fork → Actions tab → Click the green button: "I understand my workflows, go ahead and enable them"
Edit watchlist.yaml with your tech stack:
vendors:
- microsoft
- apache
- linux
products:
- chrome
- log4j
- kubernetesEither wait for the scheduled run (every hour) or:
- Go to Actions → Update Vulnerability Radar Data → Run workflow
Check data/radar_report.md in your fork — it renders beautifully in GitHub!
📺 See it in action: VulnRadar-Demo has a live example with real data.
flowchart LR
subgraph Sources["Data Sources"]
A[CVE List V5]
B[CISA KEV]
C[EPSS]
D[PatchThis]
N[NVD Feeds]
end
subgraph Core["vulnradar/ package"]
CFG[config.py\nPydantic models]
DL[downloaders.py\nHTTP fetchers]
ADL[async_downloaders.py\naiohttp parallel]
P[parsers.py\nCVE parsing]
E[enrichment.py\nKEV/EPSS/NVD merge]
R[report.py\nJinja2 templates]
end
subgraph Notify["notifications/"]
NB[base.py\nAbstract provider]
ND[discord.py]
NS[slack.py]
NT[teams.py]
NG[github_issues.py]
end
subgraph Outputs
G[radar_report.md]
H[radar_data.json]
I[GitHub Issues]
J[Discord/Slack/Teams]
end
Sources -->|sequential or --parallel| DL & ADL
DL & ADL --> P --> E
CFG --> E
E --> R --> G
E --> H
H --> Notify --> I & J
| Source | What It Provides | Update Frequency |
|---|---|---|
| CVE List V5 | All CVE records (bulk ZIP) | Daily midnight |
| NVD Data Feeds | CVSS scores, CPE, CWE, references | Daily |
| CISA KEV | Known exploited vulnerabilities | As needed |
| EPSS | Exploit probability scores (0-1) | Daily |
| PatchThis | Crowd-sourced exploit intelligence | Continuous |
VulnRadar uses watchlist.yaml to filter CVEs relevant to your tech stack.
# Add vendors (organizations)
vendors:
- microsoft
- apache
- google
# Add products (specific software)
products:
- exchange # Microsoft Exchange
- log4j # Apache Log4j
- kubernetes # Container orchestration
# Optional: exclude noise
exclude_vendors:
- n/a
- unknown
# Optional: configurable severity thresholds
thresholds:
min_cvss: 0.0 # Include all severities
min_epss: 0.0 # Include all exploit probabilities
severity_threshold: 9.0 # Also flag CVEs with CVSS >= 9.0 as critical
epss_threshold: 0.5 # Also flag CVEs with EPSS >= 50% as critical
# Optional: matching behaviour
options:
always_include_kev: true
always_include_patchthis: true
match_mode: substring # 'substring', 'exact', or 'regex'Tips:
- Matching is case-insensitive and uses substring matching by default
- See
watchlist.example.yamlfor extensive examples by category - Run
python etl.py --validate-watchlistto check for typos
VulnRadar automatically classifies findings:
| Priority | Condition | Action |
|---|---|---|
| 🔴 CRITICAL | Exploit Intel + watchlist, OR CISA KEV + watchlist, OR CVSS ≥ severity_threshold, OR EPSS ≥ epss_threshold |
Immediate attention |
| 🟠 WARNING | Has Exploit Intel (PoC) but NOT in watchlist | Shadow IT risk |
| 🟡 KEV | In CISA KEV catalog | Active exploitation |
| ⚪ Other | Watchlist match only | Monitor |
💡
severity_thresholdandepss_thresholdare optional — set them inwatchlist.yamlunderthresholds:to expand what counts as critical beyond just exploit intel.
Critical findings automatically create GitHub Issues with the vulnradar label.
Add DISCORD_WEBHOOK_URL to your repository secrets to receive Discord alerts.
See docs/discord.md for setup instructions.
Add SLACK_WEBHOOK_URL to your repository secrets to receive Slack alerts.
See docs/slack.md for setup instructions.
Add TEAMS_WEBHOOK_URL to your repository secrets to receive Teams alerts (Adaptive Cards).
See docs/teams.md for setup instructions.
Route different alert levels to different webhooks:
# In watchlist.yaml
notifications:
discord:
- url: $DISCORD_CRITICAL_WEBHOOK
filter: critical # Only critical findings
max_alerts: 25
- url: $DISCORD_ALL_WEBHOOK
filter: all # Everything
slack:
- url: $SLACK_WEBHOOK_URL
filter: kev # Only KEV entriesFilters: all | critical | kev | watchlist. URLs starting with $ are resolved from environment variables.
VulnRadar tracks which CVEs you've seen to avoid alert spam:
- First run creates a baseline (no spam for existing CVEs)
- Subsequent runs only alert on new critical CVEs
- State stored in
data/state.json
When an existing CVE's status changes (e.g., added to CISA KEV), VulnRadar posts an escalation comment on the existing issue instead of creating a duplicate.
Automatically add new issues to a GitHub Projects v2 board:
# In notify.yml workflow
- run: python notify.py --project-url https://github.com/users/YOU/projects/1For team collaboration, use watchlist.d/*.yaml:
watchlist.d/
├── infra-team.yaml # Infrastructure team's stack
├── appsec-team.yaml # AppSec team's focus areas
└── soc-team.yaml # SOC monitoring list
All files are merged at runtime.
Generate a weekly digest issue instead of individual alerts:
python notify.py --weekly-summaryFor conference presentations, inject a fake critical CVE:
python notify.py --demoIssues are automatically labeled by CVSS severity:
severity:critical(CVSS ≥ 9.0)severity:high(CVSS ≥ 7.0)severity:medium(CVSS ≥ 4.0)
One-click development environment with .devcontainer/devcontainer.json.
# Clone your fork
git clone https://github.com/YOUR_USERNAME/VulnRadar.git
cd VulnRadar
# Install dependencies
pip install -r requirements.txt
# Run the ETL
python etl.py
# View outputs
open data/radar_report.md # Markdown report
open data/radar_data.json # Raw JSON data# Scan specific year range
python etl.py --min-year 2023 --max-year 2026
# Include older KEVs outside scan window
python etl.py --include-kev-outside-window
# Skip NVD download (faster, less enrichment)
python etl.py --skip-nvd
# Use NVD cache for faster repeated runs
python etl.py --nvd-cache .nvd_cache
# Download all data sources in parallel (requires aiohttp)
python etl.py --parallel
# Write per-vendor JSON files under data/vendors/
python etl.py --vendor-split# Dry run - see what would be created
python notify.py --dry-run
# Demo mode - inject a fake CVE for presentations
python notify.py --demo
# Create weekly summary issue instead of individual alerts
python notify.py --weekly-summary
# Add issues to a GitHub Project board
python notify.py --project-url https://github.com/users/YOU/projects/1
# State management
python notify.py --reset-state # Start fresh
python notify.py --prune-state 90 # Remove CVEs not seen in 90 daysFind valid vendor/product names for your watchlist:
# List all vendors in CVE data
python etl.py --list-vendors
# Search vendors containing "micro"
python etl.py --list-vendors "micro"
# List all products
python etl.py --list-products
# Search products containing "log4"
python etl.py --list-products "log4"
# Validate your watchlist against real CVE data
python etl.py --validate-watchlistVulnRadar/
├── etl.py # Thin CLI shim → vulnradar.cli.main_etl()
├── notify.py # Thin CLI shim → vulnradar.cli.main_notify()
├── watchlist.yaml # Your configuration (edit this!)
├── watchlist.example.yaml # Extensive examples by category
├── requirements.txt # Python dependencies
├── vulnradar/ # Core package
│ ├── __init__.py # Version & public API
│ ├── cli.py # argparse entry points
│ ├── config.py # Pydantic models for watchlist + settings
│ ├── downloaders.py # Sequential HTTP fetchers (requests)
│ ├── async_downloaders.py # Parallel fetchers (aiohttp, --parallel)
│ ├── parsers.py # CVE JSON parsing, CVSS extraction
│ ├── enrichment.py # KEV/EPSS/PatchThis/NVD merge
│ ├── report.py # Jinja2 Markdown report writer
│ ├── state.py # StateManager for deduplication
│ ├── notifications/ # Strategy-pattern providers
│ │ ├── base.py # Abstract NotificationProvider
│ │ ├── discord.py # Discord webhooks
│ │ ├── slack.py # Slack webhooks
│ │ ├── teams.py # Teams Adaptive Cards
│ │ └── github_issues.py # Issues + Projects v2
│ └── templates/
│ └── report.md.j2 # Customizable report template
├── tests/ # 331 tests (pytest)
├── data/
│ ├── radar_report.md # GitHub-viewable report (auto-generated)
│ ├── radar_data.json # Machine-readable output (auto-generated)
│ ├── radar_index.json # Vendor-split manifest (with --vendor-split)
│ ├── state.json # Alert tracking state (auto-generated)
│ └── vendors/ # Per-vendor JSON files (with --vendor-split)
├── scripts/
│ ├── reset_demo.sh # Reset demo repo for presentations
│ ├── update_readme_metrics.py # Auto-update README stats
│ └── validate_watchlist.py # CI watchlist validation
├── docs/ # Full documentation
├── .devcontainer/ # GitHub Codespaces support
└── .github/workflows/
├── update.yml # Scheduled ETL (every hour)
├── notify.yml # Issue creation on new findings
└── ci.yml # Linting and tests
- No API keys required — uses only public data feeds
- No data leaves your repo — everything runs in GitHub Actions
GITHUB_TOKENis automatic — no PAT needed for basic operation- Outputs contain CVE metadata only — no secrets, no PII
| Guide | Description |
|---|---|
| Getting Started | First-time setup |
| Configuration | Watchlist deep-dive |
| Data Sources | How we gather intel |
| ETL Reference | CLI options and tuning |
| Data Schema | JSON output format |
| Automation | GitHub Actions setup |
| Troubleshooting | Common issues |
| Feature | VulnRadar | Typical Tools |
|---|---|---|
| NVD API Required | ❌ No | ✅ Yes |
| API Keys | ❌ None | ✅ Multiple |
| Self-Hosted | ✅ Your GitHub | ❌ SaaS |
| Cost | ✅ Free | 💰 Often paid |
| Setup Time | ⚡ 5 minutes | 🐌 Hours |
| GitHub Native | ✅ Issues, Actions, Markdown | ❌ External dashboards |
Contributions welcome! See CONTRIBUTING for guidelines.
MIT License — see LICENSE for details.
Radar icon by Lucide (ISC License).
See VulnRadar in action with real data: VulnRadar-Demo
Built for BSidesGalway 2026
Made with ☕ by RogoLabs