cves_by_product
Search for vulnerabilities affecting specific products or CPEs. Filter by KEV status, sort by EPSS score, and retrieve detailed vulnerability information with severity assessments.
Instructions
Search for vulnerabilities affecting specific products or CPEs. Supports filtering by KEV status, sorting by EPSS score, date ranges, and pagination. Can search by product name or CPE 2.3 identifier. Returns detailed vulnerability information including severity scores and impact assessments.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cpe23 | No | The CPE version 2.3 identifier (format: cpe:2.3:part:vendor:product:version). | |
| product | No | The name of the product to search for CVEs. | |
| count | No | If true, returns only the count of matching CVEs. | |
| is_kev | No | If true, returns only CVEs with the KEV flag set. | |
| sort_by_epss | No | If true, sorts CVEs by EPSS score in descending order. | |
| skip | No | Number of CVEs to skip (for pagination). | |
| limit | No | Maximum number of CVEs to return (max 1000). | |
| start_date | No | Start date for filtering CVEs (format: YYYY-MM-DDTHH:MM:SS). | |
| end_date | No | End date for filtering CVEs (format: YYYY-MM-DDTHH:MM:SS). |
Implementation Reference
- src/index.ts:639-744 (handler)Main execution handler for the 'cves_by_product' tool within the CallToolRequestSchema handler. Parses arguments, calls the helper function, formats the CVE data with severity assessments, and returns structured JSON response or error.case "cves_by_product": { const parsedArgs = CVEsByProductArgsSchema.safeParse(args); if (!parsedArgs.success) { throw new Error("Invalid arguments. Must provide either cpe23 or product name, but not both."); } try { const result = await queryCVEsByProduct({ cpe23: parsedArgs.data.cpe23, product: parsedArgs.data.product, count: parsedArgs.data.count, is_kev: parsedArgs.data.is_kev, sort_by_epss: parsedArgs.data.sort_by_epss, skip: parsedArgs.data.skip, limit: parsedArgs.data.limit, start_date: parsedArgs.data.start_date, end_date: parsedArgs.data.end_date }); // Helper function to format CVSS score severity const getCvssSeverity = (score: number) => { if (score >= 9.0) return "Critical"; if (score >= 7.0) return "High"; if (score >= 4.0) return "Medium"; if (score >= 0.1) return "Low"; return "None"; }; // Format the response based on whether it's a count request or full CVE list const formattedResult = parsedArgs.data.count ? { "Query Information": { "Product": parsedArgs.data.product || "N/A", "CPE 2.3": parsedArgs.data.cpe23 || "N/A", "KEV Only": parsedArgs.data.is_kev ? "Yes" : "No", "Sort by EPSS": parsedArgs.data.sort_by_epss ? "Yes" : "No" }, "Results": { "Total CVEs Found": result.total } } : { "Query Information": { "Product": parsedArgs.data.product || "N/A", "CPE 2.3": parsedArgs.data.cpe23 || "N/A", "KEV Only": parsedArgs.data.is_kev ? "Yes" : "No", "Sort by EPSS": parsedArgs.data.sort_by_epss ? "Yes" : "No", "Date Range": parsedArgs.data.start_date ? `${parsedArgs.data.start_date} to ${parsedArgs.data.end_date || 'now'}` : "All dates" }, "Results Summary": { "Total CVEs Found": result.total, "CVEs Returned": result.cves.length, "Page": `${Math.floor(parsedArgs.data.skip! / parsedArgs.data.limit!) + 1}`, "CVEs per Page": parsedArgs.data.limit }, "Vulnerabilities": result.cves.map((cve: CveResponse) => ({ "Basic Information": { "CVE ID": cve.cve_id, "Published": new Date(cve.published_time).toLocaleString(), "Summary": cve.summary }, "Severity Scores": { "CVSS v3": cve.cvss_v3 ? { "Score": cve.cvss_v3, "Severity": getCvssSeverity(cve.cvss_v3) } : "Not available", "CVSS v2": cve.cvss_v2 ? { "Score": cve.cvss_v2, "Severity": getCvssSeverity(cve.cvss_v2) } : "Not available", "EPSS": cve.epss ? { "Score": `${(cve.epss * 100).toFixed(2)}%`, "Ranking": `Top ${(cve.ranking_epss * 100).toFixed(2)}%` } : "Not available" }, "Impact Assessment": { "Known Exploited Vulnerability": cve.kev ? "Yes" : "No", "Proposed Action": cve.propose_action || "No specific action proposed", "Ransomware Campaign": cve.ransomware_campaign || "No known ransomware campaigns" }, "References": cve.references?.length > 0 ? cve.references : ["No references provided"] })) }; return { content: [ { type: "text", text: JSON.stringify(formattedResult, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text", text: error.message, }, ], isError: true, }; } }
- src/index.ts:249-271 (helper)Core helper function that performs the HTTP request to Shodan's CVEDB API (/cves endpoint) to fetch CVEs by product or CPE, handling errors appropriately.// Helper Function for CVEs by product/CPE lookups using CVEDB async function queryCVEsByProduct(params: { cpe23?: string; product?: string; count?: boolean; is_kev?: boolean; sort_by_epss?: boolean; skip?: number; limit?: number; start_date?: string; end_date?: string; }) { try { logToFile(`Querying CVEDB for CVEs with params: ${JSON.stringify(params)}`); const response = await axios.get(`${CVEDB_API_URL}/cves`, { params }); return response.data; } catch (error: any) { if (error.response?.status === 422) { throw new Error(`Invalid parameters: ${error.response.data?.detail || error.message}`); } throw new Error(`CVEDB API error: ${error.message}`); } }
- src/index.ts:180-196 (schema)Zod schema defining and validating the input parameters for the cves_by_product tool, with refinements ensuring exactly one of cpe23 or product is provided.const CVEsByProductArgsSchema = z.object({ cpe23: z.string().optional().describe("The CPE version 2.3 identifier (format: cpe:2.3:part:vendor:product:version)."), product: z.string().optional().describe("The name of the product to search for CVEs."), count: z.boolean().optional().default(false).describe("If true, returns only the count of matching CVEs."), is_kev: z.boolean().optional().default(false).describe("If true, returns only CVEs with the KEV flag set."), sort_by_epss: z.boolean().optional().default(false).describe("If true, sorts CVEs by EPSS score in descending order."), skip: z.number().optional().default(0).describe("Number of CVEs to skip (for pagination)."), limit: z.number().optional().default(1000).describe("Maximum number of CVEs to return (max 1000)."), start_date: z.string().optional().describe("Start date for filtering CVEs (format: YYYY-MM-DDTHH:MM:SS)."), end_date: z.string().optional().describe("End date for filtering CVEs (format: YYYY-MM-DDTHH:MM:SS).") }).refine( data => !(data.cpe23 && data.product), { message: "Cannot specify both cpe23 and product. Use only one." } ).refine( data => data.cpe23 || data.product, { message: "Must specify either cpe23 or product." } );
- src/index.ts:341-345 (registration)Tool registration in the ListToolsRequestSchema handler, defining the tool name, description, and linking to the input schema.{ name: "cves_by_product", description: "Search for vulnerabilities affecting specific products or CPEs. Supports filtering by KEV status, sorting by EPSS score, date ranges, and pagination. Can search by product name or CPE 2.3 identifier. Returns detailed vulnerability information including severity scores and impact assessments.", inputSchema: zodToJsonSchema(CVEsByProductArgsSchema), },