| """Tool for querying the Exploit Prediction Scoring System (EPSS)."""
|
|
|
| from smolagents import Tool
|
| import requests
|
| import json
|
|
|
| class EpsTool(Tool):
|
| """
|
| Tool for querying the Exploit Prediction Scoring System (EPSS).
|
| """
|
|
|
| name = "epss_search"
|
| description = """Tool for querying the Exploit Prediction Scoring System (EPSS).
|
|
|
| This tool allows obtaining EPSS scores for specific CVEs.
|
| Usage: epss_search(cve_id="CVE-2022-26332", date="2022-03-05")
|
|
|
| Example: epss_search(cve_id="CVE-2022-26332", date="2022-03-05")
|
|
|
| The EPSS score indicates the probability that a vulnerability will be exploited in the next 30 days.
|
| - Scores range from 0.0 to 1.0
|
| - Higher scores indicate higher probability of exploitation
|
| - Interpretation:
|
| * 0.7+ (70%+): High probability of exploitation
|
| * 0.4-0.7 (40-70%): Medium probability of exploitation
|
| * 0.0-0.4 (0-40%): Low probability of exploitation"""
|
|
|
| inputs = {
|
| "cve_id": {
|
| "description": "The CVE ID to search for EPSS score (e.g., 'CVE-2022-26332').",
|
| "type": "string",
|
| },
|
| "date": {
|
| "description": "Optional date for the EPSS score (format: YYYY-MM-DD).",
|
| "type": "string",
|
| "nullable": True,
|
| },
|
| }
|
|
|
| output_type = "string"
|
|
|
| def __init__(self):
|
| super().__init__()
|
| self.base_url = "https://api.first.org/data/v1/epss"
|
|
|
| def forward(self, cve_id: str, date: str = None) -> str:
|
| """Search for EPSS score for a specific CVE."""
|
| try:
|
|
|
| params = {"cve": cve_id}
|
| if date:
|
| params["date"] = date
|
|
|
| url = f"{self.base_url}?{'&'.join([f'{k}={v}' for k, v in params.items()])}"
|
|
|
| response = requests.get(url)
|
| response.raise_for_status()
|
| data = response.json()
|
|
|
| if not data.get('data'):
|
| return f"No EPSS data found for {cve_id}"
|
|
|
| epss_data = data['data'][0]
|
|
|
| result = f"EPSS Score for {cve_id}:\n\n"
|
| result += f"- CVE ID: {epss_data.get('cve', 'Not available')}\n"
|
| result += f"- EPSS Score: {epss_data.get('epss', 'Not available')}\n"
|
| result += f"- Percentile: {epss_data.get('percentile', 'Not available')}\n"
|
| result += f"- Date: {epss_data.get('date', 'Not available')}\n"
|
|
|
|
|
| epss_score = epss_data.get('epss')
|
| if epss_score is not None:
|
| try:
|
| score = float(epss_score)
|
| if score >= 0.7:
|
| result += f"- Interpretation: High probability of exploitation ({score:.1%})\n"
|
| elif score >= 0.4:
|
| result += f"- Interpretation: Medium probability of exploitation ({score:.1%})\n"
|
| else:
|
| result += f"- Interpretation: Low probability of exploitation ({score:.1%})\n"
|
| except ValueError:
|
| pass
|
|
|
| return result
|
|
|
| except requests.exceptions.RequestException as e:
|
| return f"Error accessing EPSS API: {str(e)}"
|
| except Exception as e:
|
| return f"Error processing EPSS data: {str(e)}"
|
|
|
| def _format_context(self, data: dict, cve_id: str) -> str:
|
| """Format the EPSS data for context."""
|
| if not data or not data.get('data'):
|
| return f"No EPSS data found for {cve_id}"
|
|
|
| epss_data = data['data'][0]
|
| context = []
|
|
|
| context.append(f"EPSS Score: {epss_data.get('epss', 'Not available')}")
|
| context.append(f"Percentile: {epss_data.get('percentile', 'Not available')}")
|
| context.append(f"Date: {epss_data.get('date', 'Not available')}")
|
|
|
|
|
| epss_score = epss_data.get('epss')
|
| if epss_score is not None:
|
| try:
|
| score = float(epss_score)
|
| if score >= 0.7:
|
| context.append(f"Risk Level: High ({score:.1%} probability of exploitation)")
|
| elif score >= 0.4:
|
| context.append(f"Risk Level: Medium ({score:.1%} probability of exploitation)")
|
| else:
|
| context.append(f"Risk Level: Low ({score:.1%} probability of exploitation)")
|
| except ValueError:
|
| pass
|
|
|
| return "\n".join(context) |