scan_library_vulnerabilities
Scan software libraries for security vulnerabilities using OSINT sources like OSV and GitHub Advisories. Get detailed reports with severity levels and recommendations.
Instructions
Comprehensive vulnerability scan using OSINT sources (OSV, GitHub Advisories, Safety DB).
Args:
library_name: Name of the library to scan (e.g., "fastapi", "react")
ecosystem: Package ecosystem ("PyPI", "npm", "Maven", "Go", etc.)
Returns:
Detailed security report with vulnerabilities, severity levels, and recommendations
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| library_name | Yes | ||
| ecosystem | No | PyPI |
Implementation Reference
- Primary MCP tool handler for 'scan_library_vulnerabilities'. Delegates to the vulnerability_scanner instance to perform the scan and formats the SecurityReport into the tool response.async def scan_library_vulnerabilities(library_name: str, ecosystem: str = "PyPI"): """ Comprehensive vulnerability scan using OSINT sources (OSV, GitHub Advisories, Safety DB). Args: library_name: Name of the library to scan (e.g., "fastapi", "react") ecosystem: Package ecosystem ("PyPI", "npm", "Maven", "Go", etc.) Returns: Detailed security report with vulnerabilities, severity levels, and recommendations """ await enforce_rate_limit("scan_library_vulnerabilities") from .vulnerability_scanner import vulnerability_scanner try: # Perform comprehensive scan security_report = await vulnerability_scanner.scan_library( library_name, ecosystem ) return { "scan_results": security_report.to_dict(), "summary": { "library": security_report.library_name, "ecosystem": security_report.ecosystem, "security_score": security_report.security_score, "risk_level": ( "π¨ High Risk" if security_report.security_score < 50 else ( "β οΈ Medium Risk" if security_report.security_score < 70 else ( "β Low Risk" if security_report.security_score < 90 else "π‘οΈ Excellent" ) ) ), "critical_vulnerabilities": security_report.critical_count, "total_vulnerabilities": security_report.total_vulnerabilities, "primary_recommendation": ( security_report.recommendations[0] if security_report.recommendations else "No specific recommendations" ), }, "scan_timestamp": security_report.scan_date, "sources": [ "OSV Database", "GitHub Security Advisories", "Safety DB (PyPI only)", ], } except Exception as e: return { "error": f"Vulnerability scan failed: {str(e)}", "library": library_name, "ecosystem": ecosystem, "scan_timestamp": datetime.now().isoformat(), }
- Core helper function implementing the vulnerability scanning logic. Scans multiple sources (OSV, GitHub Advisories, Safety DB) in parallel, generates SecurityReport, and handles caching.async def scan_library( self, library_name: str, ecosystem: str = "PyPI" ) -> SecurityReport: """ Comprehensive vulnerability scan for a library Args: library_name: Name of the library (e.g., "fastapi", "react") ecosystem: Package ecosystem ("PyPI", "npm", "Maven", etc.) Returns: SecurityReport with vulnerability details """ cache_key = f"{library_name}_{ecosystem}" # Check cache first if self._is_cached(cache_key): return self.cache[cache_key]["data"] vulnerabilities = [] # Scan multiple sources in parallel scan_tasks = [ self._scan_osv(library_name, ecosystem), self._scan_github_advisories(library_name, ecosystem), ( self._scan_safety_db(library_name) if ecosystem.lower() == "pypi" else self._empty_scan() ), ] try: results = await asyncio.gather(*scan_tasks, return_exceptions=True) for result in results: if isinstance(result, list): vulnerabilities.extend(result) elif isinstance(result, Exception): print(f"Scan error: {result}", file=sys.stderr) except Exception as e: print(f"Vulnerability scan failed for {library_name}: {e}", file=sys.stderr) # Generate security report report = self._generate_security_report( library_name, ecosystem, vulnerabilities ) # Cache the result self._cache_result(cache_key, report) return report
- Dataclass defining the structure for individual Vulnerability objects used in scan reports.@dataclass class Vulnerability: """Represents a security vulnerability""" id: str title: str description: str severity: SeverityLevel cvss_score: Optional[float] cve_id: Optional[str] affected_versions: List[str] fixed_version: Optional[str] published_date: str source: str # "osv", "github", "safety", "snyk" references: List[str] def to_dict(self) -> Dict[str, Any]: return { "id": self.id, "title": self.title, "description": ( self.description[:200] + "..." if len(self.description) > 200 else self.description ), "severity": self.severity.value, "cvss_score": self.cvss_score, "cve_id": self.cve_id, "affected_versions": self.affected_versions, "fixed_version": self.fixed_version, "published_date": self.published_date, "source": self.source, "references": self.references[:3], # Limit references }
- Dataclass defining the comprehensive SecurityReport returned by scans, including summary stats, vulnerabilities list, and recommendations.@dataclass class SecurityReport: """Comprehensive security report for a library""" library_name: str ecosystem: str # "pypi", "npm", "maven", etc. scan_date: str total_vulnerabilities: int critical_count: int high_count: int medium_count: int low_count: int security_score: float # 0-100, higher is better recommendations: List[str] vulnerabilities: List[Vulnerability] latest_secure_version: Optional[str] def to_dict(self) -> Dict[str, Any]: return { "library_name": self.library_name, "ecosystem": self.ecosystem, "scan_date": self.scan_date, "summary": { "total_vulnerabilities": self.total_vulnerabilities, "critical": self.critical_count, "high": self.high_count, "medium": self.medium_count, "low": self.low_count, "security_score": self.security_score, }, "latest_secure_version": self.latest_secure_version, "recommendations": self.recommendations, "vulnerabilities": [vuln.to_dict() for vuln in self.vulnerabilities], }
- src/documentation_search_enhanced/main.py:1254-1254 (registration)MCP tool registration decorator for the scan_library_vulnerabilities handler.async def scan_library_vulnerabilities(library_name: str, ecosystem: str = "PyPI"):