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,jqon 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:
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:
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:
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:
# 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:
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:
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:
# 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:
- Define the tech stack inventory (products + versions)
- Run bulk tech stack scan
- Identify all existing CVEs with CVSS >= 7.0
- Prioritize KEV-listed vulnerabilities
- Create remediation plan with deadlines based on severity
- Set up daily monitoring
Continuous Monitoring
Day-to-day CVE tracking:
- Daily digest generated via cron
- Alert on new CRITICAL CVEs affecting watchlist products
- Weekly full tech stack rescan
- Monthly EPSS trend analysis (are exploitation probabilities rising?)
- Quarterly CVE posture review
Incident Trigger
When a high-profile CVE drops (e.g., Log4Shell, xz backdoor):
- Immediate check against tech stack inventory
- If affected: CVE-MCP enrichment (EPSS, KEV, exploit availability)
- Cross-reference with vulnerability-scanner for validation
- Trigger incident-responder if active exploitation confirmed
- 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
