Multi-Engine Scanner
A unified project security scanner that runs Anchore Grype, Aqua Trivy, Astral Ruff and SQLFluff concurrently, deduplicates their findings, and renders them as branded, reviewable reports.
Distributed on PyPI as
multi-engine-scanner; the import package isproject_scannerand the console commands aremultiscanandmulti-engine-scanner.
pip install multi-engine-scanner
multiscan /path/to/your/project
Features
- Multi-Engine Scanning: Runs every available engine concurrently for maximum detection coverage.
- Smart Deduplication: Normalizes CVEs and package identifiers, cross-verifying findings to highlight dual-verified vulnerabilities versus tool-unique findings.
- Multi-Format Reporting:
- 📊 Interactive HTML Reports built for triage: every row states the severity, the finding in plain language, the affected component and the remediation step. Live search, severity and engine filters, sortable and paginated register, expandable detail, CSV export, print/PDF layout.
- 🗂️ Master Dashboard (
index.html) with a hierarchical left rail: executive overview → consolidated register → per-engine reports → transcript and raw exports. - 📝 GitHub-Flavored Markdown Report (ideal for pull requests and documentation).
- 📄 Structured JSON Dataset (ideal for CI/CD integration).
- 💻 Colorized Terminal Output (ideal for immediate CLI feedback).
- Run Anywhere: Can be executed from any terminal directory against any project path.
Report hierarchy
Every HTML report is laid out as a four-level review hierarchy:
| Level | Section | Contents |
|---|---|---|
| 1 | Executive summary | Posture band, Severity Weight Index, KPI tiles |
| 2 | Scan coverage | Per-engine status cards and severity distribution |
| 3 | Hierarchy explorer | Collapsible tree, regroupable by severity, component or engine |
| 4 | Findings register | Sortable, searchable table with per-finding detail panels |
The Severity Weight Index is 100 × Σ(weight × count) ÷ (10 × total), with weights
Critical 10, High 6, Medium 3, Low/Unknown 1 — i.e. 100 means every finding is critical.
Presentation lives in project_scanner/reporters/theme.py (palette, stylesheet, shared document
furniture); change the brand tokens there to restyle every report at once.
Design tokens
| Token | Value | Used for |
|---|---|---|
| Ink | #0D0C22 |
Headings and primary reading text |
| Secondary | #655C7A |
Supporting copy and descriptions |
| Accent | #060318 |
Links and primary actions |
| Metadata | #808080 |
Labels, timestamps, counts |
| Background | #FFFFFF |
Everything sits on white; structure comes from space and hairlines |
| Type | Mona Sans | 32px headings, 14px body |
| Spacing | 4px base unit | Rhythm across the whole document |
| Radius | 3px |
Surfaces and controls alike |
Severity keeps its own semantic palette (red / amber / ochre / indigo) and is always coded twice — a colour bar on the row plus a text badge — so it never depends on colour alone. Layout is responsive: two columns on desktop, one below 1080px, and under 700px the findings table becomes one card per finding rather than a horizontally scrolling grid.
Severity colours stay semantic (red / orange / amber / blue) so criticality is never carried by the
brand hue alone. The logo is an original scan-shield mark — the SVG sources are in
assets/, and the reports embed it inline so they never fetch a remote image.
Branding the reports
Reports ship with neutral naming. Point the masthead at your own organisation with environment variables — no code changes needed:
| Variable | Default | Appears as |
|---|---|---|
SCANNER_BRAND_NAME |
Multi-Engine Scanner |
Masthead heading |
SCANNER_BRAND_UNIT |
Security & Code Quality Assurance |
Line under the heading |
SCANNER_BRAND_TAGLINE |
Automated Multi-Engine Vulnerability Reporting |
Small caps strapline |
SCANNER_REPORT_CLASSIFICATION |
Internal · Confidential |
Classification banner |
SCANNER_DOC_PREFIX |
SEC-VA |
Document reference, e.g. SEC-VA-20260801-CON |
export SCANNER_BRAND_NAME="Your Organisation"
export SCANNER_BRAND_UNIT="Information Security Office"
multiscan /path/to/project
Installation
Requires Python 3.9 or newer on macOS, Linux or Windows.
Step 1 — install the scanner
The scanner itself is pure Python standard library, so this command is the same everywhere:
pip install multi-engine-scanner
Installing into a virtual environment is recommended. The only difference between platforms is how you activate it:
macOS / Linux
python3 -m venv .venv
source .venv/bin/activate
pip install multi-engine-scanner
Windows (PowerShell)
py -m venv .venv
.venv\Scripts\Activate.ps1
pip install multi-engine-scanner
If activation is blocked by execution policy, run
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass first, or use
.venv\Scripts\activate.bat from cmd.exe.
Step 2 — install the scanning engines
Each engine is a separate tool the scanner shells out to.Install the ones you care about — any
engine that is missing is reported as MISSING_BINARY in the report rather than failing the run.
| Engine | Scope | Type |
|---|---|---|
| Anchore Grype | Dependency & SBOM CVE matching | Go binary |
| Aqua Trivy | Filesystem, lockfile & misconfiguration | Go binary |
| Astral Ruff | Python static analysis | Python package |
| SQLFluff | SQL linting & query hygiene | Python package |
Ruff and SQLFluff come from PyPI on every platform:
pip install "multi-engine-scanner[engines]"
Grype and Trivy are native binaries, so they differ per platform:
macOS
brew install grype trivy
Linux
# Grype - official install script
curl -sSfL https://get.anchore.io/grype | sudo sh -s -- -b /usr/local/bin
# Trivy - official install script
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
Distribution packages work too. Debian / Ubuntu:
sudo apt-get install wget gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install trivy
Homebrew on Linux also works: brew install grype trivy.
Windows
With Chocolatey in an elevated PowerShell:
choco install grype trivy
Without a package manager, download the release archives, unzip them, and add the folder to your
PATH:
- Grype — https://github.com/anchore/grype/releases (
grype_*_windows_amd64.zip) - Trivy — https://github.com/aquasecurity/trivy/releases (
trivy_*_windows-64bit.zip)
# add an unzipped folder to PATH for the current session
$env:PATH += ";C:\tools\grype;C:\tools\trivy"
WSL2 is a good alternative on Windows — install inside the Linux distribution using the Linux
commands above and scan your project through the /mnt/c/... path.
Note: releases are built and tested on Linux CI. macOS is used daily for development; Windows is supported on a best-effort basis. Use a modern terminal (Windows Terminal or PowerShell 7) so the colourised CLI output renders correctly.
Step 3 — verify
multiscan --help
grype version
trivy --version
ruff --version
sqlfluff --version
Every engine reports its own status in the generated report, so you can also just run a scan and read the engine coverage cards.
From source
git clone https://gitlab.com/chandrabrt/multi-engine-scanner.git
cd multi-engine-scanner
pip install -e ".[dev,engines]"
You can also invoke it as a module without installing the console scripts:
python -m project_scanner /path/to/project
CLI Usage Examples
Scan Current Directory
multiscan
Scan Specific Project Directory
multiscan /path/to/your/project
Specify Output Directory & Formats
multiscan /path/to/target --out-dir ./security-reports --format html,markdown
Filter Minimum Severity
multiscan /path/to/target --min-severity HIGH
Run Single Scanner Only
multiscan /path/to/target --grype-only
# or --trivy-only / --ruff-only / --sqlfluff-only
Auto-fix Python findings
--fix hands the target to Ruff's autofixer before reporting, so the run both repairs what it
safely can and tells you what is left.
multiscan --fix
multiscan /path/to/target --fix
This rewrites source files in place. Commit or stash your work first — the scanner prints a warning but will not stop you. Output looks like:
🛠️ Ruff auto-fixed 4 finding(s); 4 remain for manual review.
By default only fixes Ruff considers safe are applied. Add --unsafe-fixes to apply the rest:
multiscan /path/to/target --fix --unsafe-fixes
Unsafe fixes can change behaviour. Removing an unused assignment, for example, deletes the value it held —
PASSWORD = "hunter2"disappears along with theF841warning. Review the diff.
--fix applies to Ruff only; Grype, Trivy and SQLFluff findings are always reported, never
modified. Combining it with --grype-only, --trivy-only or --sqlfluff-only is a no-op and warns.
Choose which Ruff rules apply
Rule selection follows Ruff's rule selection rules.
--ruff-select replaces the default set (E,F,S,W,C,I,B,ASYNC) and --ruff-ignore removes rules
from it. Both also govern what --fix will touch.
# security rules only (Bandit-derived S rules)
multiscan /path/to/target --ruff-only --ruff-select S
# everything except line-length and import-sorting
multiscan /path/to/target --ruff-ignore E501,I001
# fix import ordering and unused imports, nothing else
multiscan /path/to/target --ruff-select I,F401 --fix
Report the installed version
multiscan --version
Output
Reports are written to <target>/vulnerability_reports/ — <target>\vulnerability_reports\ on
Windows — and the location can be overridden with --out-dir:
| File | Contents |
|---|---|
index.html |
Master dashboard — open this first |
combined_report.html |
Consolidated, deduplicated register |
<engine>_report.html |
One report per engine |
combined_report.md |
Markdown transcript for merge requests |
combined_report.json |
Structured dataset for CI/CD |
Check what is installed at any time with:
multiscan --version
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file multi_engine_scanner-0.2.8.tar.gz.
File metadata
- Download URL: multi_engine_scanner-0.2.8.tar.gz
- Upload date:
- Size: 555.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85c632255758df6fcacf071c7b3fd32e3ecb6ea2a2ac9a187c817930907f7104
|
|
| MD5 |
5957756591deac08521167eab04e2391
|
|
| BLAKE2b-256 |
301c8de704c455808a81707ee4a4fda26e0ebd784bb29cefcd66d830f0b74485
|
File details
Details for the file multi_engine_scanner-0.2.8-py3-none-any.whl.
File metadata
- Download URL: multi_engine_scanner-0.2.8-py3-none-any.whl
- Upload date:
- Size: 59.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
297ded7de1ddab1c09ac49cd27a82c733f71aa24e4b1957a13aeb7201912d704
|
|
| MD5 |
7583a542ada0a6dc27a34a92a04025b8
|
|
| BLAKE2b-256 |
70850c8193324337b76b40006031ac433eda495fe5515b80a3e21981110f288e
|