Some checks are pending
Bump version / Bump version and create changelog with commitizen (push) Waiting to run
Tests / test (macos-latest, 3.10) (push) Waiting to run
Tests / test (macos-latest, 3.11) (push) Waiting to run
Tests / test (macos-latest, 3.12) (push) Waiting to run
Tests / test (ubuntu-latest, 3.10) (push) Waiting to run
Tests / test (ubuntu-latest, 3.11) (push) Waiting to run
Tests / test (ubuntu-latest, 3.12) (push) Waiting to run
Tests / test (windows-latest, 3.10) (push) Waiting to run
Tests / test (windows-latest, 3.11) (push) Waiting to run
Tests / test (windows-latest, 3.12) (push) Waiting to run
Tests / security (push) Waiting to run
- Add security vulnerability scanning with OSV and GitHub advisories integration - Add license compatibility analysis with SPDX normalization and risk assessment - Add package health scoring across 7 categories with GitHub metrics integration - Add requirements file analysis supporting multiple formats (requirements.txt, pyproject.toml, etc.) - Fix search functionality MCP wrapper and error handling - Fix Python compatibility checking parameter order issue - Fix package recommendations NoneType handling - Add 8 new MCP tool endpoints for enhanced analysis capabilities This brings the total to 37 comprehensive MCP tools across 8 categories for complete PyPI package analysis and management.
147 lines
6.0 KiB
Python
147 lines
6.0 KiB
Python
"""Security vulnerability scanning tools for PyPI packages."""
|
|
|
|
import logging
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from ..core.exceptions import InvalidPackageNameError, NetworkError, SearchError
|
|
from ..tools.security import bulk_security_scan, scan_package_security
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def scan_pypi_package_security(
|
|
package_name: str,
|
|
version: Optional[str] = None,
|
|
include_dependencies: bool = True,
|
|
severity_filter: Optional[str] = None
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Scan a PyPI package for security vulnerabilities.
|
|
|
|
This tool performs comprehensive security vulnerability scanning of PyPI packages,
|
|
checking against multiple vulnerability databases including OSV (Open Source Vulnerabilities),
|
|
GitHub Security Advisories, and analyzing package metadata for security indicators.
|
|
|
|
Args:
|
|
package_name: Name of the package to scan for vulnerabilities
|
|
version: Specific version to scan (optional, defaults to latest version)
|
|
include_dependencies: Whether to scan package dependencies for vulnerabilities
|
|
severity_filter: Filter results by severity level (low, medium, high, critical)
|
|
|
|
Returns:
|
|
Dictionary containing comprehensive security scan results including:
|
|
- Total vulnerability count and severity breakdown
|
|
- Direct package vulnerabilities vs dependency vulnerabilities
|
|
- Risk score and level assessment (minimal, low, medium, high, critical)
|
|
- Detailed vulnerability information with IDs, descriptions, and references
|
|
- Package metadata security analysis
|
|
- Actionable security recommendations
|
|
|
|
Raises:
|
|
InvalidPackageNameError: If package name is empty or invalid
|
|
PackageNotFoundError: If package is not found on PyPI
|
|
NetworkError: For network-related errors
|
|
SearchError: If security scanning fails
|
|
"""
|
|
if not package_name or not package_name.strip():
|
|
raise InvalidPackageNameError(package_name)
|
|
|
|
logger.info(f"MCP tool: Scanning security for package {package_name}")
|
|
|
|
try:
|
|
result = await scan_package_security(
|
|
package_name=package_name,
|
|
version=version,
|
|
include_dependencies=include_dependencies,
|
|
severity_filter=severity_filter
|
|
)
|
|
|
|
logger.info(f"MCP tool: Security scan completed for {package_name} - found {result.get('security_summary', {}).get('total_vulnerabilities', 0)} vulnerabilities")
|
|
return result
|
|
|
|
except (InvalidPackageNameError, NetworkError, SearchError) as e:
|
|
logger.error(f"Error scanning security for {package_name}: {e}")
|
|
return {
|
|
"error": f"Security scan failed: {e}",
|
|
"error_type": type(e).__name__,
|
|
"package": package_name,
|
|
"version": version,
|
|
"scan_timestamp": "",
|
|
"security_summary": {
|
|
"total_vulnerabilities": 0,
|
|
"direct_vulnerabilities": 0,
|
|
"dependency_vulnerabilities": 0,
|
|
"severity_breakdown": {"critical": 0, "high": 0, "medium": 0, "low": 0, "unknown": 0},
|
|
"risk_score": 0,
|
|
"risk_level": "unknown",
|
|
},
|
|
"vulnerabilities": {"direct": [], "dependencies": []},
|
|
"metadata_analysis": {},
|
|
"recommendations": [f"❌ Security scan failed: {e}"],
|
|
"scan_details": {
|
|
"sources_checked": [],
|
|
"dependencies_scanned": False,
|
|
"scan_completion": "error",
|
|
}
|
|
}
|
|
|
|
|
|
async def bulk_scan_package_security(
|
|
package_names: List[str],
|
|
include_dependencies: bool = False,
|
|
severity_threshold: str = "medium"
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Perform bulk security scanning of multiple PyPI packages.
|
|
|
|
This tool scans multiple packages simultaneously for security vulnerabilities,
|
|
providing a consolidated report with summary statistics and prioritized
|
|
recommendations for addressing security issues across your package ecosystem.
|
|
|
|
Args:
|
|
package_names: List of package names to scan for vulnerabilities
|
|
include_dependencies: Whether to include dependency vulnerability scanning
|
|
severity_threshold: Minimum severity level to report (low, medium, high, critical)
|
|
|
|
Returns:
|
|
Dictionary containing bulk scan results including:
|
|
- Summary statistics (total packages, packages with vulnerabilities, high-risk packages)
|
|
- Detailed scan results for each package
|
|
- Prioritized recommendations for security remediation
|
|
- Scan timestamp and completion status
|
|
|
|
Raises:
|
|
ValueError: If package_names list is empty
|
|
NetworkError: For network-related errors during scanning
|
|
SearchError: If bulk scanning fails
|
|
"""
|
|
if not package_names:
|
|
raise ValueError("Package names list cannot be empty")
|
|
|
|
logger.info(f"MCP tool: Starting bulk security scan of {len(package_names)} packages")
|
|
|
|
try:
|
|
result = await bulk_security_scan(
|
|
package_names=package_names,
|
|
include_dependencies=include_dependencies,
|
|
severity_threshold=severity_threshold
|
|
)
|
|
|
|
logger.info(f"MCP tool: Bulk security scan completed - {result.get('summary', {}).get('packages_with_vulnerabilities', 0)} packages have vulnerabilities")
|
|
return result
|
|
|
|
except (ValueError, NetworkError, SearchError) as e:
|
|
logger.error(f"Error in bulk security scan: {e}")
|
|
return {
|
|
"error": f"Bulk security scan failed: {e}",
|
|
"error_type": type(e).__name__,
|
|
"summary": {
|
|
"total_packages": len(package_names),
|
|
"packages_with_vulnerabilities": 0,
|
|
"total_vulnerabilities": 0,
|
|
"high_risk_packages": [],
|
|
"scan_timestamp": ""
|
|
},
|
|
"detailed_results": {},
|
|
"recommendations": [f"❌ Bulk security scan failed: {e}"]
|
|
} |