Skip to content

[REFACTOR] Deduplicate scan_X methods in scanner.py into generic _scan_by_plugin #30

Description

@KbWen

Problem Description

scanner.py contains approximately 15 nearly identical scan_X() methods (scan_dependencies, scan_secrets, scan_rules, scan_docker, scan_iac, scan_ci, scan_firebase, scan_mcp, scan_agency, scan_vulnerabilities, scan_mobile, scan_api, scan_entropy, scan_ai_supply_chain).

Each method follows the exact same pattern:

def scan_X(self, limit_files=None):
    findings = []
    plugin = next((p for p in self.scanners if "X" in getattr(p, 'name', '').lower()), None)
    if not plugin: return []
    for root, files in self._iter_files(limit_files):
        for file in files:
            file_path = os.path.join(root, file)
            if not self._is_safe_path(file_path):
                continue
            findings.extend(plugin.scan([file_path], self.config))
    return findings

This creates ~200 lines of duplicated code that must be maintained in parallel.

Proposed Refactor

Replace all scan_X methods with a single generic method:

def _scan_by_plugin(self, plugin_name_match: str, limit_files=None, file_filter=None):
    """Generic scan method that delegates to a specific plugin by name match."""
    findings = []
    plugin = next((p for p in self.scanners if plugin_name_match in getattr(p, 'name', '').lower()), None)
    if not plugin:
        return []
    for root, files in self._iter_files(limit_files):
        for file in files:
            if file_filter and not file_filter(file):
                continue
            file_path = os.path.join(root, file)
            if not self._is_safe_path(file_path):
                continue
            findings.extend(plugin.scan([file_path], self.config))
    return findings

Then each public method becomes a one-liner:

def scan_docker(self, limit_files=None):
    return self._scan_by_plugin("docker", limit_files)

def scan_dependencies(self, limit_files=None):
    return self._scan_by_plugin("hallucination", limit_files, 
        file_filter=lambda f: f in ['requirements.txt', 'package.json'])

Impact

  • Reduces ~200 lines to ~30 lines
  • Easier to add new scan commands in the future
  • Single place to fix bugs in the iteration/safety logic

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions