testssl_scan.py•4.95 kB
"""
Advanced SSL/TLS Check Tool using testssl.sh - Windows/WSL Compatible
Comprehensive SSL/TLS security analysis using testssl.sh
Optional advanced tool - requires testssl.sh to be installed
"""
from typing import Dict, Any, List
from .base_tool import BaseTool
import subprocess
import platform
class TestSSLTool(BaseTool):
"""Advanced SSL/TLS security analysis using testssl.sh"""
def __init__(self):
super().__init__()
self.name = "testssl_scan"
self.description = "Comprehensive SSL/TLS security scan using testssl.sh. Provides detailed analysis of certificates, protocols, cipher suites, and vulnerabilities."
# Path to testssl.sh (adjust based on your installation)
self.testssl_path = "/mnt/c/Users/kramamoorthy/OneDrive - Microsoft/Desktop/Kannan/Tools/testssl.sh-3.1dev/testssl.sh-3.1dev/testssl.sh"
def get_tool_definition(self) -> Dict[str, Any]:
"""Return MCP-compatible tool definition"""
return {
"name": self.name,
"description": self.description,
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Target domain to scan (e.g., google.com or github.com)"
},
"scan_type": {
"type": "string",
"description": "Type of scan: 'quick' (fast), 'standard' (default), or 'full' (comprehensive)",
"enum": ["quick", "standard", "full"],
"default": "standard"
}
},
"required": ["target"]
}
}
async def execute(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Execute testssl.sh scan"""
try:
target = arguments.get("target", "")
scan_type = arguments.get("scan_type", "standard")
if not target:
return self.format_error("Target domain is required")
# Clean up target
target = target.replace("https://", "").replace("http://", "").split("/")[0]
# Build testssl.sh command based on scan type
if scan_type == "quick":
# Quick scan: protocols and basic vulnerabilities
testssl_args = "--fast --protocols --vulnerabilities"
elif scan_type == "full":
# Full scan: everything
testssl_args = "--wide --protocols --server-defaults --server-preference --cipher-per-proto --vulnerabilities"
else:
# Standard scan
testssl_args = "--protocols --server-defaults --vulnerabilities"
# Build full command with PROPER QUOTING for paths with spaces
# This is the FIX! Added quotes around the path
cmd = f'"{self.testssl_path}" {testssl_args} {target}'
# Detect platform
is_windows = platform.system() == 'Windows'
if is_windows:
# Use WSL on Windows
exec_cmd = ["wsl", "bash", "-c", cmd]
else:
# Direct execution on Linux/Mac
exec_cmd = ["bash", "-c", cmd]
# Execute testssl.sh
try:
result = subprocess.run(
exec_cmd,
capture_output=True,
text=True,
timeout=300 # 5 minutes max
)
if result.returncode == 0 or result.stdout:
# testssl.sh often returns non-zero even on success
output = result.stdout if result.stdout else result.stderr
# Format output
formatted = f"""✅ TestSSL Comprehensive Analysis for {target}
{'='*60}
Scan Type: {scan_type}
{output}
{'='*60}
Note: For detailed HTML report, run testssl.sh with --htmlfile option
"""
return self.format_success(formatted)
else:
error = result.stderr or "testssl.sh scan failed"
return self.format_error(f"TestSSL scan error: {error}")
except FileNotFoundError:
return self.format_error(f"testssl.sh not found at {self.testssl_path}. Please verify the path or install testssl.sh.")
except subprocess.TimeoutExpired:
return self.format_error("TestSSL scan timeout (exceeded 5 minutes)")
except Exception as e:
return self.format_error(f"Execution failed: {str(e)}")
# ✅ TOOL IS NOW ENABLED!
# The line below registers the tool so the LLM can use it
tool_instance = TestSSLTool()