Skill v1.0.0
currentLLM-judged scan90/100version: "1.0.0" name: new-scanner description: Scaffold a new vulnerability scanner implementation with tests following the project's existing pattern. Use when adding support for a new scanner tool. allowed-tools: Bash Read Write Edit arguments: [name, cli, example_image, example_sbom] argument-hint: <scanner-name> <cli-executable> "<image scan command>" "<sbom scan command>"
New Scanner
Scaffold a complete scanner implementation for $name using the $cli CLI tool.
Validate `$name` first: it must be a valid Python identifier (lowercase letters, numbers, underscores only). If it contains dashes, spaces, or other invalid characters, normalize it (e.g., my-scanner becomes my_scanner) and use the normalized form for file names, class names, and method names throughout.
Step 1: Discover the CLI
Run $cli --help to learn available subcommands and flags. Identify:
- The version flag (e.g.,
--version,version) - How to scan an SBOM file
- How to scan a container image
- How to get JSON output
Step 2: Discover the JSON structure
Run both example commands provided by the user:
Image scan:
$example_image
SBOM scan:
$example_sbom
Inspect the JSON output from each and identify:
- Where vulnerability entries live in the JSON hierarchy
- The field name for the vulnerability/CVE ID
- The field names for package name and installed version
Step 3: Read the existing pattern
Read these files to understand the conventions:
diffused/diffused/scanners/base.py— abstract base class with 4 required methodsdiffused/diffused/scanners/trivy.py— reference implementationdiffused/diffused/scanners/registry.py— theSCANNERSmap where scanners are registereddiffused/tests/scanners/test_trivy.py— reference test structurediffused/tests/conftest.py— shared fixtures (test_image,test_sbom_path)
Step 4: Create the scanner implementation
Create diffused/diffused/scanners/$name.py:
- Subclass
BaseScanner - Implement all 4 abstract methods using the discovered CLI commands and JSON structure:
scan_sbom()— run the scanner onself.sbom, parse JSON intoself.raw_resultscan_image()— run the scanner onself.image, parse JSON intoself.raw_resultprocess_result()— parseself.raw_resultintoself.processed_result(adefaultdict[str, set[Package]]mapping CVE IDs to sets of Package objects)get_version()— static method, return the scanner version string- Add a
_run_$name_command(self, cmd, operation)helper with 120s timeout - Follow the error handling convention: store errors in
self.error, do not raise from scan/process methods - Use
loggingfor all log messages
Step 5: Create the test file
Create diffused/tests/scanners/test_$name.py:
- Use the discovered JSON output as sample test data in fixtures
- Cover: initialization, scan_sbom, scan_image, process_result, get_version
- Use
unittest.mock(patch,MagicMock) for subprocess mocking - Reuse fixtures from
conftest.py(test_image,test_sbom_path) - Follow the same test structure as
test_trivy.py
Step 6: Register the scanner
Edit diffused/diffused/scanners/registry.py:
- Add an import for the new scanner class
- Add an entry to the
SCANNERSdict (used byget_scanner_class(), which bothVulnerabilityDifferandScanReportselect scanners through)
Edit diffusedcli/diffusedcli/cli.py:
- Add
$nameto theclick.Choicelist in the--scanneroption - Check for any scanner-specific restrictions in the CLI commands (e.g., SBOM scanning guards) and update them if the new scanner supports those features
Step 7: Run tests
Run tox -e py39-pytest,py39-pytest-cli and fix any failures until tests pass with 100% code coverage on the new scanner file.
Step 8: Summary
Present a summary:
- Files created and modified
- CLI commands and JSON fields discovered
- Any manual steps remaining