🛡️ 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 in a corporate theme (light/dark, live search, severity and engine filters, sortable + paginated register, expandable finding 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.
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
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 |
Releasing
Releases are cut by tagging; .gitlab-ci.yml lints, builds, smoke-tests the wheel, verifies the tag
matches project_scanner.__version__, and publishes to PyPI via Trusted Publishing.
# bump __version__ in project_scanner/__init__.py and update CHANGELOG.md first
git tag v0.2.0
git push origin v0.2.0
To build and publish by hand, use publish.sh — it lints, builds, validates metadata,
smoke-tests the wheel in a clean environment and asks for confirmation before uploading:
./publish.sh # upload to PyPI
./publish.sh --dry-run # build and verify only
./publish.sh --test # upload to TestPyPI
./publish.sh --verbose # show PyPI's full response when an upload fails
Credentials come from ~/.pypirc (see .pypirc.example) or from
TWINE_USERNAME=__token__ and TWINE_PASSWORD, which take precedence over the file.
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.1.tar.gz.
File metadata
- Download URL: multi_engine_scanner-0.2.1.tar.gz
- Upload date:
- Size: 39.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3983f3c772decdeeecdd4492a9e0cc128c6d58f491764db9f54c02d4ad3dede7
|
|
| MD5 |
f559bd0c4a3f6fe6c50fe6a0c9bc7906
|
|
| BLAKE2b-256 |
0d99a6ccc388239f82f6b16ee941b9f941716f608018aafa4061d8939670bf40
|
File details
Details for the file multi_engine_scanner-0.2.1-py3-none-any.whl.
File metadata
- Download URL: multi_engine_scanner-0.2.1-py3-none-any.whl
- Upload date:
- Size: 47.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f2bfee739382ef8c742426598c959bd54b23a21d5053e467859f5fe983e90d9
|
|
| MD5 |
e56475f4d3a9adeb5ac45633c300b14c
|
|
| BLAKE2b-256 |
c807e6214fd91ec6cbe32e559ab8d7cef38a0403b2248bfc11e02632e93d869c
|