File size: 10,152 Bytes
52b089b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import requests
from typing import Optional
from smolagents import Tool

class CVEDBTool(Tool):
    """

    Tool for searching vulnerabilities using Shodan's CVEDB API (free, no API key required).

    """
    
    name = "cvedb_search"
    description = """Tool for searching vulnerabilities using Shodan's CVEDB API (free, no API key required).

    

    REQUIRED PARAMETERS:

    - search_type: Must be 'cve' for specific CVE ID or 'product' for product name search

    - identifier: The CVE ID or product name to search for

    

    This tool allows searching for vulnerabilities in two ways:

    1. For a specific CVE: cvedb_search(search_type="cve", identifier="CVE-2021-44228")

    2. For a product: cvedb_search(search_type="product", identifier="microsoft")

    

    CRITICAL - Product name format for product search:

    - ALWAYS use ONLY the base product name, NEVER include versions

    - CORRECT examples: "log4j", "apache", "microsoft", "chrome", "tomcat", "nginx"

    - INCORRECT examples: "log4j 2.14.1", "apache http server", "microsoft windows", "chrome 120.0.6099.109"

    - When searching, strip version numbers and descriptive words

    - Example: "Apache Tomcat 9.0.65" → search for "tomcat"

    - Example: "Google Chrome 120.0.6099.109" → search for "chrome"

    - Example: "Log4j 2.14.1" → search for "log4j"

    

    CORRECT Usage examples:

    - cvedb_search(search_type="cve", identifier="CVE-2021-44228")

    - cvedb_search(search_type="product", identifier="microsoft")

    - cvedb_search(search_type="product", identifier="mobaxterm")

    

    INCORRECT Usage (will cause errors):

    - cvedb_search(identifier="microsoft")  # Missing search_type

    - cvedb_search(search_type="product")   # Missing identifier"""
    
    inputs = {
        "search_type": {
            "description": "Type of search to perform. Must be 'cve' for specific CVE ID or 'product' for product name search.",
            "type": "string",
        },
        "identifier": {
            "description": "The CVE ID (e.g., 'CVE-2021-44228') or product name (e.g., 'microsoft'). For products, use ONLY base product names without versions (e.g., 'microsoft' not 'microsoft windows').",
            "type": "string",
        },
    }
    
    output_type = "string"
    
    def __init__(self):
        super().__init__()

    def forward(self, search_type: str, identifier: str) -> str:
        """Search for vulnerabilities in CVEDB."""
        try:
            import requests
            
            if search_type == "cve":
                return self._search_by_cve(identifier)
            elif search_type == "product":
                return self._search_by_product(identifier)
            else:
                return "Error: search_type must be 'cve' or 'product'"
                
        except Exception as e:
            return f"Error searching CVEDB: {str(e)}"

    def _search_by_cve(self, cve_id: str) -> str:
        """Search for a specific CVE."""
        import requests
        
        url = f"https://cvedb.shodan.io/cve/{cve_id}"
        
        try:
            response = requests.get(url)
            response.raise_for_status()
            data = response.json()
            
            if not data:
                return f"No vulnerabilities found for CVE {cve_id}"
            
            result = f"Vulnerability found for {cve_id}:\n\n"
            result += f"- CVE ID: {data.get('cve_id', 'Not available')}\n"
            result += f"- Summary: {data.get('summary', 'Not available')}\n"
            result += f"- CVSS Score: {data.get('cvss', 'Not available')}\n"
            result += f"- CVSS Version: {data.get('cvss_version', 'Not available')}\n"
            result += f"- CVSS V2: {data.get('cvss_v2', 'Not available')}\n"
            result += f"- CVSS V3: {data.get('cvss_v3', 'Not available')}\n"
            result += f"- EPSS Score: {data.get('epss', 'Not available')}\n"
            result += f"- EPSS Ranking: {data.get('ranking_epss', 'Not available')}\n"
            result += f"- Known as exploitable (KEV): {'Yes' if data.get('kev') else 'No'}\n"
            result += f"- Propose Action: {data.get('propose_action', 'Not available')}\n"
            result += f"- Ransomware Campaign: {data.get('ransomware_campaign', 'Not available')}\n"
            result += f"- Publication Date: {data.get('published_time', 'Not available')}\n"
            
            # Show references
            references = data.get('references', [])
            if references:
                result += f"- References ({len(references)} total):\n"
                for i, ref in enumerate(references[:10], 1):  # Show first 10 references
                    result += f"  {i}. {ref}\n"
                if len(references) > 10:
                    result += f"  ... and {len(references) - 10} more references\n"
            else:
                result += "- References: None\n"
            
            # Show CPE count but not the full list
            cpes = data.get('cpes', [])
            if cpes:
                result += f"- Affected CPEs: {len(cpes)} CPEs found (list omitted due to length)\n"
            else:
                result += "- Affected CPEs: None\n"
            
            return result
            
        except requests.exceptions.RequestException as e:
            return f"Error accessing CVEDB API: {str(e)}"

    def _search_by_product(self, product: str) -> str:
        """Search for vulnerabilities by product."""
        import requests
        
        # Convert product name to lowercase for consistent search
        product = product.lower()
        
        url = f"https://cvedb.shodan.io/cves"
        params = {"product": product}
        
        try:
            response = requests.get(url, params=params)
            response.raise_for_status()
            data = response.json()
            
            if not data or not data.get('cves'):
                return f"No vulnerabilities found for the product {product}"
            
            result = f"Vulnerabilities found for {product}:\n\n"
            
            # Show all vulnerabilities
            for i, vuln in enumerate(data['cves']):
                result += f"**Vulnerability {i+1}:**\n"
                result += f"- CVE ID: {vuln.get('cve_id', vuln.get('id', 'Not available'))}\n"
                result += f"- Summary: {vuln.get('summary', 'Not available')}\n"
                result += f"- CVSS Score: {vuln.get('cvss', 'Not available')}\n"
                result += f"- CVSS Version: {vuln.get('cvss_version', 'Not available')}\n"
                result += f"- CVSS V2: {vuln.get('cvss_v2', 'Not available')}\n"
                result += f"- CVSS V3: {vuln.get('cvss_v3', 'Not available')}\n"
                result += f"- EPSS Score: {vuln.get('epss', 'Not available')}\n"
                result += f"- EPSS Ranking: {vuln.get('ranking_epss', 'Not available')}\n"
                result += f"- Known as exploitable (KEV): {'Yes' if vuln.get('kev') else 'No'}\n"
                result += f"- Propose Action: {vuln.get('propose_action', 'Not available')}\n"
                result += f"- Ransomware Campaign: {vuln.get('ransomware_campaign', 'Not available')}\n"
                result += f"- Publication Date: {vuln.get('published_time', 'Not available')}\n"
                
                # Show references count
                references = vuln.get('references', [])
                if references:
                    result += f"- References: {len(references)} references available\n"
                else:
                    result += "- References: None\n"
                
                # Show CPE count but not the full list
                cpes = vuln.get('cpes', [])
                if cpes:
                    result += f"- Affected CPEs: {len(cpes)} CPEs found (list omitted due to length)\n"
                else:
                    result += "- Affected CPEs: None\n"
                
                result += "\n"
            
            return result
            
        except requests.exceptions.RequestException as e:
            return f"Error accessing CVEDB API: {str(e)}"

    def _format_context(self, data: dict, search_type: str, identifier: str) -> str:
        """Format the data for context."""
        context = []
        
        if search_type == "cve":
            if not data:
                return f"No vulnerabilities found for CVE {identifier}"
            
            context.append(f"CVSS Score: {data['cvss']}")
            context.append(f"EPSS Score: {data['epss']}")
            context.append(f"Known as exploitable (KEV): {'Yes' if data.get('kev') else 'No'}")
            
            # Important dates
            if data.get('published_time'):
                context.append(f"Publication Date: {data['published_time']}")
            
            context.append(f"Summary: {data.get('summary', 'Not available')}")
            
            # Important references
            if data.get('references'):
                context.append("\nImportant references:")
                for ref in data['references'][:3]:  # Show first 3 references
                    context.append(f"- {ref}")
        
        elif search_type == "product":
            if not data or not data.get('cves'):
                return "No vulnerabilities found for this product."
            
            context.append(f"Found {len(data['cves'])} vulnerabilities for this product.")
            context.append("\nMost relevant vulnerabilities:")
            
            # Show all vulnerabilities
            for i, vuln in enumerate(data['cves']):
                context.append(f"{i+1}. {vuln.get('id', 'Unknown CVE')} - CVSS: {vuln.get('cvss', 'N/A')}")
            
            if len(data['cves']) > 5:
                context.append(f"\n... and {len(data['cves']) - 5} more vulnerabilities")
        
        return "\n".join(context)