-
Notifications
You must be signed in to change notification settings - Fork 389
CVE Intel
cve_intel is the agent's tool for structured CVE intelligence. It wraps the ProjectDiscovery vulnx CLI (the successor to cvemap), which aggregates seven public CVE data sources into a single, queryable, JSON-first API.
Use it when you need exploitability scoring, KEV status, EPSS, public PoC links, or Nuclei template availability — i.e., the structured answers that semantic search (web_search) can't give you reliably.
For implementation internals (MCP wiring, env-var injection, Pattern-2 silent key flow, regression test suite), see the integration in
mcp/servers/network_recon_server.pyandagentic/tools.py. For the original tool integration prompt, see readmes/coding_agent_prompts/PROMPT.ADD_AGENTIC_TOOL.md.
The agent already had web_search with an nvd source for CVE descriptions, and a Knowledge Base with the NVD corpus. So why add another one?
| Question class | Best tool | Why |
|---|---|---|
| "What is CVE-2024-21887?" (description, prose) | web_search(include_sources=["nvd"]) |
Semantic match on the textual description |
| "What's the EPSS for CVE-2024-21887? Is it KEV-listed?" | cve_intel |
Structured numeric / boolean fields |
| "List 10 KEV-listed Confluence CVEs with EPSS > 0.5 and a Nuclei template" | cve_intel |
Compound lucene filter; embeddings can't answer this |
| "How do I exploit Spring4Shell?" |
tradecraft_lookup / web_search(exploitdb)
|
Methodology / PoCs |
cve_intel adds the structured query axis that the others lack. The dataset it queries is updated every ~6 hours and includes:
- NVD (NIST CVE database)
- CISA KEV Catalog (Known Exploited Vulnerabilities, with due dates and ransomware-use flags)
- EPSS (Exploit Prediction Scoring System — probability score 0-1, plus percentile)
- HackerOne CVE Discovery (bounty hunter reports)
- Public GitHub PoCs (with rankings and reference links)
- Nuclei templates (which CVEs have ready-to-run YAML detection templates)
- CPE mappings (Common Platform Enumeration vendor/product/version)
cve_intel(args: str, api_key: str = "") -> strThe agent only ever supplies args. The optional api_key is silently injected by the PhaseAwareToolExecutor from your Global Settings — the LLM never sees it, never reasons about it, and any value it tries to pass is overridden.
| Subcommand | Purpose | Example args
|
|---|---|---|
id |
Single-CVE full intel record | id CVE-2024-21887 --json |
search |
Multi-CVE lucene query | search 'severity:critical AND is_kev:true' --json --limit 10 |
filters |
Print all 69 searchable fields (schema discovery) | filters |
analyze |
Aggregate counts by field | analyze --field affected_products.vendor --json |
healthcheck |
Validate connectivity / authentication state | healthcheck |
The tool description trains the agent to always include --json --limit N. For multi-record search queries, it should also pass --fields cve_id,severity,epss_score,is_kev,is_template to slash token usage — the full record is large (~18 KB per CVE).
Other useful output flags: --silent (suppress banners), --offset N (paginate beyond limit), --detailed (full record).
search accepts a lucene-style query string with all the usual primitives:
| Primitive | Example |
|---|---|
| Boolean operators | severity:critical AND is_kev:true |
| Negation | NOT vstatus:rejected |
| Numeric ranges |
cvss_score:>7, epss_score:>=0.5, age_in_days:<30
|
| Wildcards | vendor:apache* |
| Phrase search | description:"buffer overflow" |
| Grouping | (vendor:apache OR vendor:nginx) AND severity:critical |
The full list (69 fields) is available via cve_intel("filters"). The most useful ones for pentest triage:
| Category | Fields |
|---|---|
| Severity / score |
severity, cvss_score, epss_score, epss_percentile
|
| Exploitability flags |
is_kev (CISA actively-exploited), is_template (Nuclei template exists), is_poc, is_remote, is_hackerone
|
| Identity |
cve_id, cwe, vuln_type (rce / sqli / xss / ...), tags
|
| Affected products |
vendor, product, affected_products.vendor, affected_products.product
|
| Time / status |
age_in_days, cve_created_at, vstatus (confirmed / new / modified / rejected) |
| Text |
description, references
|
Tip —
vstatus:confirmed: NVD includes rejected and disputed CVEs. AddingAND vstatus:confirmedto most search queries removes noise from the result set.
cve_intel("id CVE-2024-21887 --json")
Returns a full record: CVSS metrics, EPSS, KEV details (CISA due date, ransomware flag), all known PoCs, all Nuclei templates, HackerOne reports, CWE, references, vendor/product mappings.
cve_intel("search 'epss_score:>0.7 AND is_template:true AND vstatus:confirmed' --json --fields cve_id,severity,epss_score --limit 20")
Returns CVEs that are: (a) very likely to be exploited in the wild (EPSS > 0.7), (b) have a Nuclei template ready to run, and (c) are confirmed (not rejected). These are the ones to hand straight to execute_nuclei.
cve_intel("search 'product:confluence AND is_kev:true' --json --limit 10")
For triaging an in-scope target — what KEV-listed CVEs affect this product?
cve_intel("search 'is_kev:true AND age_in_days:<30' --json --fields cve_id,severity,epss_score --limit 50")
CVEs added to CISA KEV in the last 30 days — the freshest exploitation candidates.
cve_intel("filters")
Run this when you need a filter not in the description. Returns the full list of 69 searchable fields with their types and example values.
| Phase | Allowed |
|---|---|
| Informational | ✅ |
| Exploitation | ✅ |
| Post-Exploitation | ✅ |
cve_intel is passive — every query goes to ProjectDiscovery's cloud, never to your pentest target. There's no scenario where it's gated.
It's also not classified as a dangerous tool (no REQUIRE_TOOL_CONFIRMATION prompt) and has no Rules of Engagement category — RoE forbiddings don't apply because there's no traffic to a target.
Stealth mode applies NO RESTRICTIONS to cve_intel. The query path is agent → cve_intel MCP wrapper → vulnx → cloud.projectdiscovery.io, with no bytes ever leaving your network in the direction of a pentest target.
cve_intel works fully without an API key — anonymous use is rate-limited to 10 requests/minute, which is sufficient for interactive chat. Without the key, you'll see standard responses; under heavy bursts you might hit a 429 Too Many Requests notice from upstream.
To lift the rate limit:
- Sign up for a free ProjectDiscovery Cloud Platform account.
- Open Global Settings → API Keys (in the Global Settings page at
/settings). - Paste the key into the PDCP API Key field (badge:
[AI Agent]). - Save. The key is masked, stored per-user in the database.
- The next chat session will pick up the key automatically.
The key is never stored in environment variables, Docker build args, or docker-compose.yml. The orchestrator reads it from your Global Settings on every session init and the executor injects it into the per-call subprocess environment as PDCP_API_KEY. The LLM never sees the key, and the key never appears in argv (so it can't leak via ps aux).
Like other API keys in Global Settings, the PDCP key supports rotation: paste extra keys in the rotation modal and the system will round-robin through them after every N calls (default: 10). Useful only if you hit a single-key rate limit, which is rare for chat use.
This is the canonical workflow for CVE triage on an active engagement:
1. query_graph: "What CVEs are on hosts in scope?"
→ Returns CVE-2024-X, CVE-2024-Y on confluence.example.com:443
2. cve_intel("id CVE-2024-X --json"), cve_intel("id CVE-2024-Y --json") (parallel)
→ Returns: CVE-2024-X has is_template=true and EPSS=0.92 (exploit it now)
CVE-2024-Y has is_template=false and EPSS=0.04 (deprioritize)
3. execute_nuclei("-u https://confluence.example.com -id CVE-2024-X -jsonl")
→ Verify the high-leverage candidate
The agent does this chaining autonomously. You just ask the high-level question.
| You want... | Pick |
|---|---|
| A prose description of what a CVE does | web_search(include_sources=["nvd"]) |
| Numeric scores, KEV flag, PoC count, template availability | cve_intel |
To filter by cvss_score > 7 AND is_kev:true
|
cve_intel (impossible with web_search) |
| To search "Apache RCE CVEs from 2024" semantically | Either — but cve_intel("search 'vendor:apache AND tags:rce AND cve_created_at:>2024-01-01'") is faster and structured |
| Exploit PoCs / write-ups |
web_search(include_sources=["exploitdb"]) or tradecraft_lookup
|
The agent's tool registry makes this routing automatic — when the question maps to structured fields, cve_intel is preferred.
vulnx emits JSON when --json is passed (always do). A single-CVE id lookup returns a deeply nested object; multi-record search returns a JSON array.
| Field | Type | Meaning |
|---|---|---|
cve_id |
string | The CVE identifier |
severity |
string |
critical / high / medium / low
|
cvss_score |
number | CVSS v3.1 base score (0–10) |
cvss_metrics |
string | Full CVSS vector string |
epss_score |
number | Exploit Prediction Scoring System score (0–1) |
epss_percentile |
number | Percentile rank of the EPSS score |
is_kev |
boolean | In CISA KEV catalog (actively exploited) |
is_template |
boolean | A Nuclei template exists for this CVE |
is_poc |
boolean | Public PoC exists |
is_remote |
boolean | Remotely exploitable |
is_hackerone |
boolean | Reported on HackerOne |
kev[] |
array | KEV details: added_date, due_date, known_ransomware_campaign_use, source
|
affected_products[] |
array |
vendor, product, version_ranges
|
references[] |
array | URLs (NVD, vendor advisory, exploit-db, etc.) |
nuclei_templates[] |
array | Template paths for execute_nuclei
|
pocs[] |
array | PoC URLs (often GitHub) |
cwe / cwe_id
|
string / array | CWE category mapping |
Wrapper-level pre-processing (handled by the MCP function, transparent to the agent):
- ANSI escape codes are stripped from stdout/stderr.
-
[INF]info lines, version banners, and "using default config" lines are filtered from stderr. -
Genuine errors in stderr are surfaced to the agent prefixed with
[STDERR]. -
Empty results return
[INFO] No CVEs matched the queryinstead of an empty string. -
Subprocess timeout: 60 seconds. If you see a timeout, narrow your filters (add
--limit, drop a wildcard). -
Output truncation: the central
TOOL_OUTPUT_MAX_CHARScap (default 40,000) applies, so the agent self-throttles via--limitand--fields.
| Property | Guarantee |
|---|---|
| No traffic to pentest target | ✅ — queries hit cloud.projectdiscovery.io only |
| API key never in image / env / argv | ✅ — per-user storage, env-var injection per call only |
| LLM cannot see or leak the key | ✅ — silent injection by executor, override of any LLM-supplied value |
| Key rotation supported | ✅ — like all other tools in Global Settings |
| Anonymous mode supported | ✅ — works fully without any key (10 req/min) |
| Shell injection safe | ✅ — argv form, never shell=True, metacharacters pass through as literals |
| Output truncation | ✅ — 60s subprocess timeout + 40 KB tool output cap |
"vulnx not found"
The kali-sandbox container doesn't have vulnx installed. Rebuild: docker compose build kali-sandbox && docker compose up -d kali-sandbox.
"timed out after 60 seconds"
Your filter is too broad. Add --limit, narrow the search (severity:critical, vstatus:confirmed, age_in_days:<90), or use --fields f1,f2 to pull less data per record.
"Rate limit exceeded! API key required for higher limits" You hit the 10 req/min anonymous cap. Configure a PDCP API key in Global Settings.
Empty result [INFO] No CVEs matched the query
Either the query is genuinely zero-match, or the lucene syntax is malformed. Try cve_intel("filters") to validate field names, then simplify the query and re-add filters one at a time.
Agent won't pick cve_intel
Check that cve_intel is enabled in the project's Tool Matrix for the current phase. By default it's allowed in all 3 phases. If a project predates the cve_intel rollout, the SQL backfill in README.md → Rollout ensures agent_tool_phase_map includes cve_intel.
-
Knowledge Base & Web Search — semantic CVE search via
web_search(nvd) - Global Settings — where the optional PDCP API key lives
- Agent Tools Reference (in AI-Agent-Guide) — the full tool catalog
- vulnx GitHub — upstream CLI
- ProjectDiscovery Cloud Platform — sign up for the optional API key
Getting Started
Core Workflow
- Red Zone
- Recon Pipeline Workflow
- Running Reconnaissance
- AI Agent Guide
- Fireteam — Parallel Specialists
- Reverse Shells
Scanning & OSINT
- JS Reconnaissance
- GraphQL Security Testing
- Subdomain Takeover Detection
- VHost & SNI Enumeration
- GVM Vulnerability Scanning
- GitHub Secret Hunting
- TruffleHog Secret Scanning
AI & Automation
- AI Model Providers
- MCP Tool Plugins
- Knowledge Base & Web Search
- Agent Skills
- Chat Skills
- Tradecraft Lookup
- Playwright Browser Automation
- CypherFix — Automated Remediation
- Rules of Engagement (RoE)
HackLab
Analysis & Reporting
- Insights Dashboard
- Pentest Reports
- Attack Surface Graph
- Surface Shaper
- EvoGraph — Attack Chain Evolution
- Data Export & Import
Contributing
Reference & Help