Scan a target then use a local LLM to interactively remediate findings. Checks prerequisites for each finding before offering to execute. Supports: localhost hardening, web headers, SSL, firewall, services. Examples: secsuite ai remediate localhost -p ollama -m qwen2.5:7b
(
target: str = typer.Argument(..., help="Target to scan and remediate (use 'localhost' for this machine)"),
provider: str = typer.Option("ollama", "--provider", "-p", help="LLM provider (ollama/anthropic/openai)"),
model: Optional[str] = typer.Option(None, "--model", "-m", help="Model name (e.g. qwen2.5:7b)"),
base_url: Optional[str] = typer.Option(None, "--base-url", "-b", help="Ollama/custom API base URL"),
severity: str = typer.Option("medium", "--severity", "-s", help="Minimum severity to remediate: critical/high/medium/low"),
dry_run: bool = typer.Option(False, "--dry-run", help="Show commands without executing"),
quick: bool = typer.Option(False, "--quick", "-q", help="Quick scan (fewer modules)"),
skip_scan: bool = typer.Option(False, "--skip-scan", help="Skip scan phase, use last cached results if available"),
)
| 829 | console.print(f" {chain.description}") |
| 830 | |
| 831 | # Display recommendations |
| 832 | if report.recommendations: |
| 833 | console.print() |
| 834 | console.print("[bold green]Recommendations:[/bold green]") |
| 835 | for rec in report.recommendations: |
| 836 | console.print(f" • {rec}") |
| 837 | |
| 838 | |
| 839 | @ai_app.command("remediate") |
| 840 | def ai_remediate( |
| 841 | target: str = typer.Argument(..., help="Target to scan and remediate (use 'localhost' for this machine)"), |
| 842 | provider: str = typer.Option("ollama", "--provider", "-p", help="LLM provider (ollama/anthropic/openai)"), |
| 843 | model: str | None = typer.Option(None, "--model", "-m", help="Model name (e.g. qwen2.5:7b)"), |
| 844 | base_url: str | None = typer.Option(None, "--base-url", "-b", help="Ollama/custom API base URL"), |
| 845 | severity: str = typer.Option("medium", "--severity", "-s", help="Minimum severity to remediate: critical/high/medium/low"), |
| 846 | dry_run: bool = typer.Option(False, "--dry-run", help="Show commands without executing"), |
| 847 | quick: bool = typer.Option(False, "--quick", "-q", help="Quick scan (fewer modules)"), |
| 848 | skip_scan: bool = typer.Option(False, "--skip-scan", help="Skip scan phase, use last cached results if available"), |
| 849 | ): |
| 850 | """ |
| 851 | Scan a target then use a local LLM to interactively remediate findings. |
| 852 | |
| 853 | Checks prerequisites for each finding before offering to execute. |
| 854 | Supports: localhost hardening, web headers, SSL, firewall, services. |
| 855 | |
| 856 | Examples: |
| 857 | secsuite ai remediate localhost -p ollama -m qwen2.5:7b |
| 858 | secsuite ai remediate localhost --dry-run |
| 859 | secsuite ai remediate https://example.com -s high |
| 860 | """ |
| 861 | from core.models import Severity as SevEnum |
| 862 | from modules.ai import RemediationCopilot |
| 863 | |
| 864 | setup_logging() |
| 865 | |
| 866 | SEV_MAP = { |
| 867 | "critical": SevEnum.CRITICAL, |
| 868 | "high": SevEnum.HIGH, |
| 869 | "medium": SevEnum.MEDIUM, |
| 870 | "low": SevEnum.LOW, |
| 871 | } |
| 872 | min_sev = SEV_MAP.get(severity.lower(), SevEnum.MEDIUM) |
| 873 | |
| 874 | # ── Severity colour helper ──────────────────────────────────────────────── |
| 875 | SEV_STYLE = { |
| 876 | "critical": "bold red", |
| 877 | "high": "red", |
| 878 | "medium": "yellow", |
| 879 | "low": "blue", |
| 880 | "info": "dim", |
| 881 | } |
| 882 | |
| 883 | # ── Scan phase ──────────────────────────────────────────────────────────── |
| 884 | console.print(f"\n[bold cyan]SecSuite AI Remediation[/bold cyan] — {target}") |
| 885 | console.print(f"[dim]Provider: {provider} Model: {model or 'auto'} Min-severity: {severity} Dry-run: {dry_run}[/dim]\n") |
| 886 | |
| 887 | if not skip_scan: |
| 888 | if quick or target in ("localhost", "127.0.0.1"): |
nothing calls this directly
no test coverage detected