Automated CVE monitoring and alerting for tech stacks — NVD/NIST API integration, CVE-MCP enrichment, EPSS scoring, KEV catalog tracking. Daily digests with...
---
name: cve-tracker
description: Automated CVE monitoring and alerting for tech stacks — NVD/NIST API integration, CVE-MCP enrichment, EPSS scoring, KEV catalog tracking. Daily digests with prioritized remediation.
homepage: https://github.com/nousresearch/argus
metadata:
openclaw:
requires:
bins: ["curl", "jq"]
mcps: ["cve-mcp"]
optional_bins: ["nmap", "trivy"]
os: ["linux"]
---
# CVE Tracker
Automated CVE monitoring and alerting system for technology stacks. Continuously tracks the NVD/NIST database, enriches findings with EPSS scoring and CISA KEV catalog data via CVE-MCP, and delivers prioritized daily digests. Designed for security teams who need to know about relevant vulnerabilities before attackers do.
Runs on ARGUS infrastructure with CVE-MCP integration.
## Prerequisites
- **ARGUS host** with shell access
- **CVE-MCP** available on localhost for CVE enrichment
- `curl`, `jq` on PATH
- Technology stack inventory file (see Configuration)
## Infrastructure
| Component | Location | Purpose |
|-----------|----------|---------|
| NVD API 2.0 | `services.nvd.nist.gov` | Primary CVE data source |
| CVE-MCP | localhost MCP | CVE enrichment + EPSS + KEV |
| ARGUS cron | local | Scheduled monitoring jobs |
## Core Commands
### Define Technology Stack
Create a tech stack inventory that the tracker monitors:
```bash
cat > /tmp/tech-stack.json << 'EOF'
{
"stack_name": "production-infrastructure",
"last_updated": "2026-07-04",
"products": [
{"name": "nginx", "version": "1.24.0", "category": "web-server"},
{"name": "postgresql", "version": "15.3", "category": "database"},
{"name": "redis", "version": "7.0.11", "category": "cache"},
{"name": "nodejs", "version": "20.11.0", "category": "runtime"},
{"name": "openssl", "version": "3.0.8", "category": "crypto"},
{"name": "kubernetes", "version": "1.28.0", "category": "orchestration"},
{"name": "docker", "version": "24.0.5", "category": "container"},
{"name": "python", "version": "3.11.4", "category": "runtime"},
{"name": "gitlab", "version": "16.8.0", "category": "devops"},
{"name": "haproxy", "version": "2.8.1", "category": "load-balancer"}
],
"watchlist": [
"openssl", "nginx", "postgresql", "kubernetes", "docker"
],
"ignore_cve": []
}
EOF
```
### Single Product CVE Check
Check CVEs for one product via CVE-MCP:
```bash
PRODUCT="openssl"
VERSION="3.0.8"
echo "=== CVE Check: $PRODUCT $VERSION ==="
curl -s -X POST "http://localhost:8765/cve-mcp/search" \
-H "Content-Type: application/json" \
-d "{\"product\": \"$PRODUCT\", \"version\": \"$VERSION\"}" | \
jq '.[] | {
cve: .id,
cvss: .cvss_score,
severity: .severity,
published: .published_date,
kev: .cisa_kev,
epss: .epss_score,
exploit_available: .exploit_available,
fixed_in: .fixed_version,
summary: .description[:120]
}' | head -60
```
### Bulk Tech Stack Scan
Scan entire tech stack and produce a prioritized report:
```bash
STACK_FILE="/tmp/tech-stack.json"
REPORT_DIR="$HOME/App/domains/argus/reports/cve-tracker"
REPORT_FILE="$REPORT_DIR/cve-report-$(date +%Y%m%d-%H%M%S).json"
mkdir -p "$REPORT_DIR"
echo "=== CVE Tracker: Bulk Tech Stack Scan ==="
echo "Stack: $(jq -r '.stack_name' "$STACK_FILE")"
echo "Products: $(jq '.products | length' "$STACK_FILE")"
echo ""
# Initialize report
echo '{"scan_date": "'$(date -Iseconds)'", "findings": []}' > "$REPORT_FILE"
# Scan each product
jq -c '.products[]' "$STACK_FILE" | while IFS= read -r product; do
name=$(echo "$product" | jq -r '.name')
version=$(echo "$product" | jq -r '.version')
echo "--- $name $version ---"
result=$(curl -s -X POST "http://localhost:8765/cve-mcp/search" \
-H "Content-Type: application/json" \
-d "{\"product\": \"$name\", \"version\": \"$version\"}" 2>/dev/null)
if [ -n "$result" ] && [ "$result" != "null" ] && [ "$result" != "[]" ]; then
cve_count=$(echo "$result" | jq 'length')
echo " Found: $cve_count CVEs"
# Prioritize: KEV + EPSS first
echo "$result" | jq -c --arg product "$name" --arg version "$version" '.[] | {
product: $product,
version: $version,
cve: .id,
cvss: .cvss_score,
severity: .severity,
kev: .cisa_kev,
epss: .epss_score,
exploit: .exploit_available,
fixed: .fixed_version
}' >> "$REPORT_DIR/tmp-findings.jsonl"
else
echo " No CVEs found"
fi
done
# Compile final report
if [ -f "$REPORT_DIR/tmp-findings.jsonl" ]; then
echo ""
echo "=== Prioritized Findings ==="
# Sort by severity: KEV first, then CVSS descending
jq -s 'sort_by(
(if .kev == true then 0 else 1 end),
(if .cvss then -.cvss else 999 end)
)' "$REPORT_DIR/tmp-findings.jsonl" > "$REPORT_FILE.tmp"
# Move to final report
jq --argjson findings "$(cat "$REPORT_FILE.tmp")" \
'.findings = $findings' "$REPORT_FILE" > "${REPORT_FILE}.final"
mv "${REPORT_FILE}.final" "$REPORT_FILE"
# Print summary
total=$(jq '.findings | length' "$REPORT_FILE")
critical=$(jq '[.findings[] | select(.cvss >= 9.0)] | length' "$REPORT_FILE")
high=$(jq '[.findings[] | select(.cvss >= 7.0 and .cvss < 9.0)] | length' "$REPORT_FILE")
kev=$(jq '[.findings[] | select(.kev == true)] | length' "$REPORT_FILE")
with_exploit=$(jq '[.findings[] | select(.exploit == true)] | length' "$REPORT_FILE")
echo ""
echo "Summary:"
echo " Total CVEs: $total"
echo " Critical (≥9.0): $critical"
echo " High (7.0-8.9): $high"
echo " CISA KEV: $kev"
echo " Exploit available: $with_exploit"
echo ""
echo "Report: $REPORT_FILE"
# Show top 5 most critical
echo ""
echo "=== Top 5 Most Critical ==="
jq -r '.findings[:5][] | " \(.cve) | \(.product) \(.version) | CVSS:\(.cvss) | KEV:\(.kev) | Exploit:\(.exploit)"' "$REPORT_FILE"
rm -f "$REPORT_DIR/tmp-findings.jsonl" "$REPORT_FILE.tmp"
fi
```
### NVD API 2.0 — Recent CVEs
Fetch recently published CVEs directly from NVD:
```bash
# Last 24 hours, moderate+ severity
NVD_API="https://services.nvd.nist.gov/rest/json/cves/2.0"
curl -s "${NVD_API}?pubStartDate=$(date -d '24 hours ago' -Iseconds | sed 's/+.*//')&pubEndDate=$(date -Iseconds | sed 's/+.*//')&cvssV3Severity=CRITICAL&resultsPerPage=20" | \
jq '.vulnerabilities[] | {
cve: .cve.id,
published: .cve.published,
cvss: .cve.metrics.cvssMetricV31[0].cvssData.baseScore,
severity: .cve.metrics.cvssMetricV31[0].cvssData.baseSeverity,
vector: .cve.metrics.cvssMetricV31[0].cvssData.vectorString,
description: .cve.descriptions[0].value[:150]
}'
```
### KEV Catalog Check
Check CISA Known Exploited Vulnerabilities catalog for your products:
```bash
STACK_FILE="/tmp/tech-stack.json"
echo "=== CISA KEV Catalog Check ==="
# Get watchlist products
jq -r '.watchlist[]' "$STACK_FILE" | while IFS= read -r product; do
echo "--- $product ---"
curl -s -X POST "http://localhost:8765/cve-mcp/search" \
-H "Content-Type: application/json" \
-d "{\"product\": \"$product\", \"kev_only\": true}" | \
jq -r '.[] | " \(.id) — \(.description[:100])"'
done
```
### EPSS Score Lookup
Get EPSS (Exploit Prediction Scoring System) scores:
```bash
CVE="CVE-2024-3094"
curl -s -X POST "http://localhost:8765/cve-mcp/epss" \
-H "Content-Type: application/json" \
-d "{\"cve_id\": \"$CVE\"}" | jq '{
cve: .cve_id,
epss_score: .epss,
percentile: .percentile,
date: .date,
interpretation: (
if .epss >= 0.5 then "HIGH — likely exploited within 30 days"
elif .epss >= 0.1 then "MEDIUM — moderate exploitation probability"
else "LOW — unlikely to be exploited"
end
)
}'
```
### Daily Digest Cron Job
Set up a daily CVE digest as an ARGUS cron job:
```bash
# This would be registered as a cron job in ~/.hermes/cron/
# Command to run daily:
DAILY_DIGEST_SCRIPT="$HOME/App/domains/argus/clawhub-skills/cve-tracker/daily-digest.sh"
cat > "$DAILY_DIGEST_SCRIPT" << 'CRONEOF'
#!/bin/bash
STACK_FILE="$HOME/App/domains/argus/clawhub-skills/cve-tracker/tech-stack.json"
DIGEST_DIR="$HOME/App/domains/argus/reports/cve-tracker/digests"
mkdir -p "$DIGEST_DIR"
DIGEST="$DIGEST_DIR/digest-$(date +%Y%m%d).md"
echo "# CVE Daily Digest — $(date +%Y-%m-%d)" > "$DIGEST"
echo "" >> "$DIGEST"
# Check each product in watchlist
jq -r '.watchlist[]' "$STACK_FILE" | while IFS= read -r product; do
result=$(curl -s -X POST "http://localhost:8765/cve-mcp/search" \
-H "Content-Type: application/json" \
-d "{\"product\": \"$product\", \"days\": 7}" 2>/dev/null)
count=$(echo "$result" | jq 'length' 2>/dev/null || echo "0")
echo "## $product — $count new CVEs this week" >> "$DIGEST"
if [ "$count" -gt 0 ]; then
echo "$result" | jq -r '.[] |
"- **\(.id)** (CVSS \(.cvss_score)): \(.description[:100])\n KEV: \(.cisa_kev) | EPSS: \(.epss_score) | Exploit: \(.exploit_available)"
' >> "$DIGEST" 2>/dev/null
fi
echo "" >> "$DIGEST"
done
echo "Digest written: $DIGEST"
CRONEOF
chmod +x "$DAILY_DIGEST_SCRIPT"
echo "Daily digest script created: $DAILY_DIGEST_SCRIPT"
```
## Usage Patterns
### Initial Tech Stack Audit
When onboarding a new system:
1. Define the tech stack inventory (products + versions)
2. Run bulk tech stack scan
3. Identify all existing CVEs with CVSS >= 7.0
4. Prioritize KEV-listed vulnerabilities
5. Create remediation plan with deadlines based on severity
6. Set up daily monitoring
### Continuous Monitoring
Day-to-day CVE tracking:
1. Daily digest generated via cron
2. Alert on new CRITICAL CVEs affecting watchlist products
3. Weekly full tech stack rescan
4. Monthly EPSS trend analysis (are exploitation probabilities rising?)
5. Quarterly CVE posture review
### Incident Trigger
When a high-profile CVE drops (e.g., Log4Shell, xz backdoor):
1. Immediate check against tech stack inventory
2. If affected: CVE-MCP enrichment (EPSS, KEV, exploit availability)
3. Cross-reference with vulnerability-scanner for validation
4. Trigger incident-responder if active exploitation confirmed
5. Generate emergency advisory for team
## Pricing Tiers
### Free (Basic)
- Tech stack inventory (up to 10 products)
- Weekly manual CVE check via CVE-MCP
- 10 CVE lookups/day
- Text-only digest
- Single user
### Pro ($19/month)
- Unlimited products in tech stack
- Daily automated digest (email/webhook)
- KEV catalog monitoring with alerting
- EPSS scoring on all findings
- Bulk CVE search (100 queries/day)
- Priority alerting: CRITICAL CVEs within 1 hour
- Historical CVE trend data
- 5 team members
### Enterprise ($99/month)
- Unlimited everything
- Real-time NVD API monitoring (15-minute polling)
- Custom risk scoring rules
- CI/CD webhook integration
- SBOM-based CVE matching
- SLA: critical alert within 15 minutes
- API access for custom integrations
- Dedicated success manager
## Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `CVE_MCP_URL` | `http://localhost:8765/cve-mcp` | CVE-MCP endpoint |
| `NVD_API_URL` | `https://services.nvd.nist.gov/rest/json/cves/2.0` | NVD API 2.0 endpoint |
| `TECH_STACK_FILE` | `./clawhub-skills/cve-tracker/tech-stack.json` | Product inventory |
| `DIGEST_DIR` | `~/App/domains/argus/reports/cve-tracker/digests` | Daily digest output |
| `DIGEST_CRON_SCHEDULE` | `0 8 * * *` | Daily digest schedule (8 AM) |
| `ALERT_THRESHOLD_CVSS` | `9.0` | Minimum CVSS for immediate alert |
| `ALERT_WEBHOOK` | (optional) | Slack/Discord webhook for critical alerts |
| `WATCHLIST_ONLY` | `false` | Only monitor watchlist products |
| `SCAN_DAYS_BACK` | `7` | Days to look back for new CVEs |
## Troubleshooting
| Symptom | Likely Cause | Fix |
|---------|-------------|-----|
| NVD API returns empty | Rate limiting | NVD API allows ~5 req/30s without key; add `apiKey` param |
| CVE-MCP returns null | MCP server down | `curl http://localhost:8765/cve-mcp/health` |
| jq parse errors | Empty API response | Add `// empty` to jq filters for null safety |
| Daily digest empty | No new CVEs this week | Normal — check tech stack file for correctness |
| EPSS scores missing | EPSS not in CVE-MCP response | EPSS only available for CVEs with CVSS v3 scores |
| Too many results | Broad product match | Use specific version in tech stack, not wildcards |
## Security
- **API key management** — NVD API key via environment variable, never in scripts
- **Data classification** — Tech stack inventory is sensitive; encrypt at rest
- **Alert fatigue** — Configure meaningful thresholds to avoid desensitization
- **False positives** — Always verify version applicability before acting on CVE matches
- **Responsible disclosure** — Do not share CVE intelligence about third-party products publicly
- **ARGUS scope** — Only track systems you own or have authorization to monitor
## CVE-MCP Integration
CVE-MCP provides the intelligence layer:
- **CVE Lookup** — full CVE details by ID
- **Product Search** — CVEs by product + version
- **KEV Catalog** — CISA Known Exploited Vulnerabilities status
- **EPSS Scoring** — exploit prediction scores (0-1)
- **Exploit Maturity** — public exploit availability
- **CVSS Vector** — full CVSS 3.1 vector string
- **Patch Status** — fixed version and vendor advisory links
## Related Skills
- **vulnerability-scanner** — active scanning to validate CVE applicability
- **osint-investigator** — OSINT for threat actor context around CVEs
- **incident-responder** — response when tracked CVE becomes actively exploited
- **gdpr-security-auditor** — compliance impact of vulnerability remediation
don't have the plugin yet? install it then click "run inline in claude" again.