The main scan command with stats support.
(
path: Optional[Path],
repo_url: Optional[str],
config_path: Optional[Path],
output_file: Optional[Path],
report_format: str,
severity_level: str,
ai_scan: bool,
supply_chain: bool,
syntax_warnings: bool,
wizard: bool,
show_stats: bool,
debug: bool,
)
| 543 | @click.option('--ai', 'ai_scan', is_flag=True, default=False, |
| 544 | help="Enable the specialized ruleset for AI/LLM vulnerability scanning.") |
| 545 | @click.option('--supply-chain', is_flag=True, default=False, |
| 546 | help="Check project dependencies against the OSV database for known CVEs.") |
| 547 | @click.option('--syntax-warnings', is_flag=True, default=False, |
| 548 | help="Treat Python SyntaxWarnings as errors and exclude affected files.") |
| 549 | @click.option('--wizard', is_flag=True, |
| 550 | help="Launch interactive guided scan mode — ideal for first-time users.") |
| 551 | @click.option('--stats', 'show_stats', is_flag=True, default=False, |
| 552 | help=( |
| 553 | "Print a detailed performance and findings statistics table " |
| 554 | "at the end of the scan (LoC/sec, memory, engine breakdown, " |
| 555 | "top rules, top files, vulnerability density, and more)." |
| 556 | )) |
| 557 | @click.option('--debug', is_flag=True, default=False, |
| 558 | help="Show all informational/progress messages and the banner. " |
| 559 | "Without this flag only findings, warnings and errors are printed.") |
| 560 | @click.option('--msg', 'show_msg', type=bool, default=None, |
| 561 | help="Enable or disable the rotating contact message shown below the " |
| 562 | "banner (--msg=True / --msg=False). The setting persists across " |
| 563 | "future runs until changed again, so it only needs to be set once.") |
| 564 | def run_scan_command( |
| 565 | path: Optional[Path], |
| 566 | repo_url: Optional[str], |
| 567 | config_path: Optional[Path], |
| 568 | output_file: Optional[Path], |
| 569 | report_format: str, |
| 570 | severity_level: str, |
| 571 | ai_scan: bool, |
| 572 | supply_chain: bool, |
| 573 | syntax_warnings: bool, |
| 574 | wizard: bool, |
| 575 | show_stats: bool, |
| 576 | debug: bool, |
| 577 | show_msg: Optional[bool], |
| 578 | ): |
| 579 | """The main scan command with stats support.""" |
| 580 | |
| 581 | _print_banner() |
| 582 | handle_msg_flag(show_msg) |
| 583 | |
| 584 | # --- Wizard Mode --- |
| 585 | if wizard: |
| 586 | params = run_wizard() |
| 587 | |
| 588 | if params["repo_url"]: |
| 589 | try: |
| 590 | _parsed = urlparse(params["repo_url"]) |
| 591 | _hostname = _parsed.hostname or "" |
| 592 | except Exception: |
| 593 | _hostname = "" |
| 594 | |
| 595 | if _hostname not in ("github.com", "gitlab.com"): |
| 596 | raise click.BadParameter( |
| 597 | "URL must be a public GitHub or GitLab repository." |
| 598 | ) |
| 599 | with tempfile.TemporaryDirectory() as temp_dir: |
| 600 | _dbg(params["debug"], f"[*] Cloning '{params['repo_url']}' into temporary directory...") |
| 601 | subprocess.run( |
| 602 | ['git', 'clone', '--depth', '1', params["repo_url"], temp_dir], |
nothing calls this directly
no test coverage detected