search_exploits
Filter exploits by source, language, attack type, complexity, reliability, author, CVE, vendor, and product. Use structured filters to find targeted exploits with AI analysis.
Instructions
Browse and filter exploits using STRUCTURED FILTERS ONLY (no free-text query). Use this to filter by source (github, metasploit, exploitdb, nomisec, gitlab, inthewild, vulncheck_xdb, patchapalooza), language (python, ruby, etc.), LLM classification (working_poc, trojan, suspicious, scanner, stub, writeup, tool, no_code), author, min stars, code availability, CVE ID, vendor, or product. Also filter by AI analysis: attack_type (RCE, SQLi, XSS, DoS, LPE, auth_bypass, info_leak), complexity (trivial/simple/moderate/complex), reliability (reliable/unreliable/untested/theoretical), requires_auth. NOTE: To search by product name (e.g. 'OpenSSH', 'Apache'), use search_vulnerabilities instead — it has free-text query and get_vulnerability already includes exploits in the response. Examples: source='metasploit' for all Metasploit modules; attack_type='RCE' with reliability='reliable' for weaponizable RCE exploits; cve='CVE-2024-3400' for all exploits targeting a specific CVE; vendor='mitel' for all Mitel exploits.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| source | No | Filter by source | |
| language | No | Filter by language: python, ruby, go, c, etc. | |
| llm_classification | No | Filter by LLM classification | |
| attack_type | No | Filter by attack type from AI analysis (case-insensitive on input; canonical casing returned) | |
| complexity | No | Filter by exploit complexity | |
| reliability | No | Filter by exploit reliability | |
| requires_auth | No | Filter by whether exploit requires authentication | |
| author | No | Filter by author name | |
| min_stars | No | Minimum GitHub stars | |
| has_code | No | Only exploits with downloadable code | |
| cve | No | Filter by CVE ID (e.g. 'CVE-2024-3400') — returns all exploits for that CVE | |
| vendor | No | Filter by vendor name (e.g. 'mitel', 'fortinet') — returns exploits for all CVEs affecting that vendor | |
| product | No | Filter by product name (e.g. 'micollab', 'pan-os') | |
| sort | No | Sort order | |
| page | No | Page number (default: 1) | |
| per_page | No | Results per page (1-25, default: 10) |
Implementation Reference
- eip_mcp/server.py:1357-1371 (handler)The core handler function _tool_search_exploits that executes the 'search_exploits' tool logic. It validates arguments using the _EXPLOIT_SEARCH_FIELDS spec, calls api_client.search_exploits(params), and formats the result via formatters.format_exploit_search(data).
def _tool_search_exploits(args: dict[str, Any]) -> str: params: dict[str, Any] = {} _apply_field_spec(args, params, _EXPLOIT_SEARCH_FIELDS) _copy_bool_arg(args, params, "requires_auth") _copy_bool_arg(args, params, "has_code") params.setdefault("per_page", 10) if not params or all(k in ("per_page", "page", "sort") for k in params): raise ValidationError( "Provide at least one filter (source, language, cve, vendor, attack_type, etc.)." ) data = api_client.search_exploits(params) return formatters.format_exploit_search(data) - eip_mcp/server.py:476-566 (schema)Schema registration for 'search_exploits' tool in the TOOLS list. Defines name, description, annotations, and inputSchema (properties including source, language, llm_classification, attack_type, complexity, reliability, requires_auth, author, min_stars, has_code, cve, vendor, product, sort, page, per_page).
types.Tool( name="search_exploits", annotations=_ro_annotations("Search Exploits"), description=( "Browse and filter exploits using STRUCTURED FILTERS ONLY (no free-text query). " "Use this to filter by source (github, metasploit, exploitdb, nomisec, gitlab, inthewild, vulncheck_xdb, patchapalooza), language " "(python, ruby, etc.), LLM classification (working_poc, trojan, suspicious, scanner, " "stub, writeup, tool, no_code), author, min stars, code availability, CVE ID, vendor, or product. " "Also filter by AI analysis: attack_type (RCE, SQLi, XSS, DoS, LPE, auth_bypass, " "info_leak), complexity (trivial/simple/moderate/complex), reliability " "(reliable/unreliable/untested/theoretical), requires_auth. " "NOTE: To search by product name (e.g. 'OpenSSH', 'Apache'), use " "search_vulnerabilities instead — it has free-text query and get_vulnerability " "already includes exploits in the response. " "Examples: source='metasploit' for all Metasploit modules; " "attack_type='RCE' with reliability='reliable' for weaponizable RCE exploits; " "cve='CVE-2024-3400' for all exploits targeting a specific CVE; " "vendor='mitel' for all Mitel exploits." ), inputSchema={ "type": "object", "properties": { "source": { "type": "string", "enum": sorted(validators._SOURCES), "description": "Filter by source", }, "language": { "type": "string", "maxLength": 40, "description": "Filter by language: python, ruby, go, c, etc.", }, "llm_classification": { "type": "string", "enum": sorted(validators._LLM_CLASSIFICATIONS), "description": "Filter by LLM classification", }, "attack_type": { "type": "string", "enum": [ "RCE", "SQLi", "XSS", "DoS", "LPE", "auth_bypass", "info_leak", "deserialization", "other", ], "description": "Filter by attack type from AI analysis (case-insensitive on input; canonical casing returned)", }, "complexity": { "type": "string", "enum": sorted(validators._COMPLEXITIES), "description": "Filter by exploit complexity", }, "reliability": { "type": "string", "enum": sorted(validators._RELIABILITIES), "description": "Filter by exploit reliability", }, "requires_auth": { "type": "boolean", "description": "Filter by whether exploit requires authentication", }, "author": {"type": "string", "maxLength": 200, "description": "Filter by author name"}, "min_stars": {"type": "integer", "minimum": 0, "description": "Minimum GitHub stars"}, "has_code": {"type": "boolean", "description": "Only exploits with downloadable code"}, "cve": { "type": "string", "pattern": _CVE_ID_PATTERN, "maxLength": 20, "description": "Filter by CVE ID (e.g. 'CVE-2024-3400') — returns all exploits for that CVE", }, "vendor": { "type": "string", "maxLength": 100, "description": "Filter by vendor name (e.g. 'mitel', 'fortinet') — returns exploits for all CVEs affecting that vendor", }, "product": { "type": "string", "maxLength": 100, "description": "Filter by product name (e.g. 'micollab', 'pan-os')", }, "sort": {"type": "string", "enum": ["newest", "stars_desc"], "description": "Sort order"}, "page": _PAGE_SCHEMA, "per_page": _per_page_schema(maximum=25, default=10), }, }, ), - eip_mcp/server.py:1518-1532 (registration)Dispatch table entry mapping the string 'search_exploits' to the handler function _tool_search_exploits in the _TOOLS_WITH_ARGS dictionary.
_TOOLS_WITH_ARGS: dict[str, Callable[[dict[str, Any]], str]] = { "search_vulnerabilities": _tool_search, "get_vulnerability": _tool_get_vuln, "get_exploit_code": _tool_get_code, "get_exploit_analysis": _tool_get_exploit_analysis, "get_nuclei_templates": _tool_get_nuclei, "search_exploits": _tool_search_exploits, "list_authors": _tool_list_authors, "get_author": _tool_get_author, "get_cwe": _tool_get_cwe, "list_products": _tool_list_products, "lookup_alt_id": _tool_lookup_alt_id, "audit_stack": _tool_audit_stack, "generate_finding": _tool_generate_finding, } - eip_mcp/api_client.py:184-187 (helper)API client function search_exploits(params) that sends a GET request to /api/v1/exploits with the provided filters. Cleans None values from params before making the request.
def search_exploits(params: dict[str, Any]) -> dict[str, Any]: """Search/browse exploits with filters.""" clean = {k: v for k, v in params.items() if v is not None} return _request_json("/api/v1/exploits", params=clean) - eip_mcp/formatters.py:1144-1195 (helper)Formatter function format_exploit_search(data) that converts the API response into a human-readable text output with exploit ID, stars, source, language, classification, CVE, severity, CVSS, AI analysis inline data, and trojan warnings.
def format_exploit_search(data: dict[str, Any]) -> str: """Format exploit browse/search results with analysis data.""" total = data.get("total", 0) page = data.get("page", 1) total_pages = data.get("total_pages", 0) items = data.get("items", []) if total == 0: return "No exploits found matching the filters." lines = [_UNTRUSTED_NOTICE, "", f"Found {total:,} exploits (page {page}/{total_pages}):\n"] for e in items: eid = e.get("id", "?") stars = e.get("github_stars") star_str = f"★{stars}" if stars is not None else "" src = _sanitize_untrusted_text(e.get("source", "?"), max_len=30) lang = _sanitize_untrusted_text(e.get("language") or "", max_len=40) llm = _sanitize_untrusted_text(_compact_risk_label(e), max_len=40) name = _sanitize_untrusted_text(e.get("source_id") or f"exploit-{eid}", max_len=180) cve = e.get("cve_id") or "no-CVE" sev = (e.get("severity_label") or "?").upper() cvss, _cvss_vec, _cvss_ver = _effective_cvss_fields(e) cvss_str = f"CVSS:{cvss:.1f}" if cvss is not None else "" lines.append(f" [id={eid}] {star_str:>6} {src:<12} {name}") lines.append(f" {cve} {sev} {cvss_str} [{lang}] {llm}") if e.get("source_url"): lines.append(f" URL: {_safe_inline(e['source_url'], max_len=420)}") # Show analysis inline when available analysis = e.get("llm_analysis") if analysis: parts = [] if analysis.get("attack_type"): parts.append(_sanitize_untrusted_text(analysis["attack_type"], max_len=40)) if analysis.get("complexity"): parts.append(_sanitize_untrusted_text(analysis["complexity"], max_len=40)) if analysis.get("reliability"): parts.append(_sanitize_untrusted_text(analysis["reliability"], max_len=40)) if analysis.get("requires_auth") is True: parts.append("requires-auth") if parts: lines.append(f" AI: {' | '.join(parts)}") # For trojans, show deception detail if _risk_verdict(e) in ("trojan", "suspicious"): indicators = analysis.get("deception_indicators") if indicators: for ind in indicators[:2]: lines.append(f" !! {_sanitize_untrusted_text(ind, max_len=220)}") lines.append("") return "\n".join(lines)