super-scanner
An extensible, orchestration-first security scanning base package for Python.
super-scannerwraps best-in-class open-source scanning engines (Semgrep, Bandit, Trivy, Grype, OSV-Scanner, pip-audit, Checkov, detect-secrets, gitleaks, ModelScan, Prowler, …) behind one typed plugin API and one normalized findings model, so you can run an AWS CSPM sweep, a Semgrep code scan, an SCA/dependency scan, a container image scan, or a secrets scan in three lines of Python — and get back deterministic, deduplicated, SARIF/OCSF/CycloneDX-ready findings. It orchestrates; it does not reimplement.
- Runs everywhere, sends nothing. No telemetry, no analytics, no "phone home" and the core makes zero outbound network calls. Fully offline/air-gapped capable.
- Base package to build on. A lean, permissively-licensed (Apache-2.0) pure-Python core. Add engines, cloud providers, and output formats via
entry_points— no core changes, no forking. - Everything configurable. Layered config (
defaults < file < env < kwargs/CLI), per-engine settings, rules locations, offline mode, fail-on thresholds, baselines, and suppressions.
Install
pip install super-scanner # lean core (no scanner engines)
pip install "super-scanner[code]" # + Semgrep (SAST)
pip install "super-scanner[code-bandit]" # + Bandit (Python SAST)
pip install "super-scanner[secrets]" # + detect-secrets
pip install "super-scanner[sca-python]" # + pip-audit
pip install "super-scanner[iac]" # + Checkov
pip install "super-scanner[aws]" # + Prowler (AWS CSPM)
pip install "super-scanner[ci]" # curated: code+secrets+sca+container+iac
Some engines are Go/native binaries (Trivy, Grype, Syft, OSV-Scanner, gitleaks, nuclei, cosign, Prowler CLI…). Those are never shipped as Python packages — but you don't have to hunt them down: super-scanner can install them for you (see below). super-scanner doctor tells you exactly what's missing.
Requirements: Python ≥ 3.10. Pure-Python universal wheel; no compiled extensions in the core.
Auto-installing scanner tools
super-scanner ships an installer driven by per-tool configs in install_configs/ (one <tool>.yaml per tool, e.g. semgrep.yaml, trivy.yaml, prowler.yaml). It picks the best method available on your machine (pipx/pip/brew/go/script), respecting offline mode.
super-scanner setup # show what's installed / missing / how to get it
super-scanner install trivy grype nuclei # install specific tools
super-scanner install --engines semgrep,osv-scanner # install tools backing these engines
super-scanner install --all # install every tool with a config
super-scanner install trivy --dry-run # print the exact command, install nothing
super-scanner scan container nginx:latest --install-missing # install then scan
# repo bootstrap (venv + package + optional tools):
scripts/bootstrap.sh --tools "semgrep trivy grype osv-scanner"
Each config lists methods per platform; override the method with --prefer brew|pip|pipx|go|script, or point at a specific binary via [tool.super-scanner.engines.<tool>].binary_path. Nothing is installed during a normal scan unless you pass --install-missing. Add your own tools by dropping a <tool>.yaml into an install_configs/ directory (or set $SUPER_SCANNER_INSTALL_CONFIGS).
Quick start — a few lines of Python
from super_scanner import scan
# Static code analysis (Semgrep + Bandit)
report = scan.code("./src")
print(report.summary_line()) # critical=0 high=2 medium=1 ... total=5
report.to_sarif("out.sarif") # SARIF 2.1.0
report.raise_for_status(fail_on="high") # raises if any finding >= HIGH
from super_scanner import scan
report = scan.container("nginx:latest") # Trivy + Grype
report = scan.sca("./") # OSV-Scanner / pip-audit
report = scan.secrets("./") # detect-secrets / gitleaks
report = scan.iac("./infra") # Checkov (+ hadolint/tfsec/kics/cfn-lint)
report = scan.model("./model.pkl") # ModelScan (malicious model files)
report = scan.aws() # Prowler CSPM (raises NoCredentialsError if no creds)
# M1/M2 domains — same one-call shape:
report = scan.sbom("./") # Syft SBOM
report = scan.k8s("./manifests") # Kubescape / kube-bench
report = scan.license("./") # ScanCode license compliance
report = scan.malpkg("requirements.txt") # GuardDog malicious-package detection
report = scan.pii("./data") # Presidio PII discovery
report = scan.malware("./", rules=["rules.yar"]) # YARA
report = scan.provenance("img@sha256:...") # Cosign signature/SLSA verification
report = scan.scm("github.com/org/repo") # OpenSSF Scorecard
# Active scanners (require authorization for non-local targets):
report = scan.dast("http://localhost:8080") # nuclei
report = scan.network("10.0.0.0/24", authorized=True) # nmap
report = scan.tls("example.com", authorized=True) # sslyze
report = scan.api("./openapi.json", authorized=True) # schemathesis
Async & streaming
import anyio
from super_scanner import scan, ascan
report = anyio.run(lambda: ascan("code", "./src")) # async
for finding in scan.code.stream("./src"): # stream results as they arrive
print(finding.severity.name, finding.rule.id, finding.locations[0].display())
Multi-engine / multi-target builder
from super_scanner import Scan
report = (
Scan()
.with_engines("semgrep", "bandit", "detect-secrets")
.on("./src")
.config(offline=True, fail_on="high")
.options(rules=["p/owasp-top-ten", "./rules/custom.yml"])
.run()
)
Working with findings
report.summary() # {"critical": 0, "high": 2, ..., "total": 5}
report.dedup() # collapse same-finding across engines (auto on by default)
report.diff(baseline) # new vs unchanged vs absent
report.apply_suppressions(supp) # drop suppressed findings
report.fail_on("high") # count of findings >= HIGH
report.exit_code(fail_on="high") # deterministic CI exit code
# every output format:
report.to_json(); report.to_sarif(); report.to_cyclonedx(); report.to_asff()
report.to_gitlab(); report.to_junit(); report.to_csv(); report.to_html(); report.to_table()
report.to_ocsf() # AWS/Prowler findings only in M0
Command line
super-scanner doctor # which engines are available + how to install missing ones
super-scanner list-engines # JSON: every engine, status, license, integration
super-scanner scan code ./src --engines semgrep,bandit --fail-on high --format sarif --output-dir ./reports
super-scanner scan container nginx:latest --format json
super-scanner scan secrets ./ --format table
super-scanner baseline create code ./src --out .super-scanner.baseline
super-scanner scan code ./src --baseline .super-scanner.baseline --new-only --fail-on medium
super-scanner suppress --out .super-scanner-suppressions.json
super-scanner sbom ./ --format cyclonedx
super-scanner db gc # clean stale caches / temp roots
Exit codes (format-independent): 0 clean/within-threshold · 1 findings exceed --fail-on · 2 usage/config error · 3 engine execution error · 4 partial results · 5 authorization required but not attested. --exit-zero forces report-only.
Configuring engines
Config precedence (lowest → highest): built-in defaults → config file → environment variables → Python kwargs / CLI flags.
Put a [tool.super-scanner] table in pyproject.toml, or a dedicated super-scanner.toml:
[tool.super-scanner]
offline = false
redact = true # redact discovered secrets (on by default)
telemetry = false # OFF by default; nothing is ever sent anywhere
fail_on = "high"
[tool.super-scanner.engines.semgrep]
enabled = true
timeout = 900
# Rules location: registry packs, local rule files, and/or rule dirs.
# Overridable per-call via scan.code(..., rules=[...]) and $SUPER_SCANNER_SEMGREP_CONFIG.
config = ["p/security-audit", "./rules/custom.yml", "./rules/org-pack/"]
offline_rules_path = "./vendor/semgrep-rules" # used when offline = true
[tool.super-scanner.engines.semgrep.settings]
metrics = "off" # default; forced off when offline
jobs = 4
max_memory_mb = 4000
exclude = ["tests/", "vendor/"]
[tool.super-scanner.engines.trivy]
binary_path = "/opt/bin/trivy"
db_repository = "registry.internal/trivy-db"
[tool.super-scanner.plugins]
allowlist = ["my-org-scanner==1.4.*"] # only load allowlisted third-party plugins
require_signed = false
Semgrep rules location — 4 ways, one precedence
- Python:
scan.code("./src", rules=["p/owasp-top-ten", "./rules/custom.yml"]) - Env var:
SUPER_SCANNER_SEMGREP_CONFIG="p/security-audit:./rules"(OS path-list separated) - Config file:
[tool.super-scanner.engines.semgrep].config = [...] - Default:
p/defaultonline, or the pinned/vendored ruleset when offline.
Environment kill-switches (authoritative)
| Variable | Effect |
|---|---|
SUPER_SCANNER_OFFLINE=true |
No network; engines run in offline mode |
SUPER_SCANNER_TELEMETRY=false |
Telemetry off (default) — nothing sent anywhere |
SUPER_SCANNER_REDACT=true |
Redact discovered secrets from all output/logs |
SUPER_SCANNER_NETWORK_EGRESS=false |
Subprocess engines run network-off |
SUPER_SCANNER_PLUGIN_ALLOWLIST="dist-a,dist-b" |
Only load allowlisted plugins |
An env value that is safer always wins over a config-file value.
Privacy & offline use
- No telemetry, ever, by default. The core performs no outbound network calls.
super-scanner scan ... --offline(oroffline=true) guarantees engines run without network access, and forcessemgrep --metrics=offregardless of any override. - Secrets are redacted. Detected secrets are stored as SHA-256 hashes (never plaintext) and scrubbed from logs.
- Nothing executes scanned code. SAST/model scanning is static; the scanned model is never loaded/imported.
This makes super-scanner safe to run inside any company's air-gapped or regulated environment.
Extending it — build your own scanner on top
Add an engine in your own package with zero changes to super-scanner:
# my_pkg/engine.py
from super_scanner.engines.base import Capability, Engine, Integration
from super_scanner.model import Finding, Rule, Severity, PhysicalLocation
class MyEngine(Engine):
id = "my-engine"
name = "My Engine"
domain = "sast"
def capabilities(self):
return Capability(target_types=frozenset({"path"}), integration=Integration.LIBRARY)
def scan(self, target, ctx):
yield Finding(engine=self.id, domain="sast", rule=Rule(id="my.rule"),
severity=Severity.HIGH, message="found it",
locations=(PhysicalLocation(uri=str(target)),))
# my_pkg/pyproject.toml
[project.entry-points."super_scanner.engines"]
my-engine = "my_pkg.engine:MyEngine"
pip install my-pkg and it shows up in super-scanner doctor, scan("sast", ...), and everywhere else. Reporters (super_scanner.reporters) and cloud providers (super_scanner.providers) extend the same way.
What's covered
30 engines across 19 domains — all behind the same one-call API, all installable via super-scanner install.
| Domain | Engines | Extra / tool |
|---|---|---|
| SAST (code) | Semgrep, Bandit | [code], [code-bandit] |
| SCA (deps) | OSV-Scanner, pip-audit | [sca], [sca-python] |
| Secrets | detect-secrets, gitleaks, trufflehog | [secrets] |
| Container image | Trivy, Grype, Dockle | [container] (binaries) |
| SBOM | Syft (+ Trivy/Grype) | binary |
| IaC | Checkov, hadolint, tfsec, KICS, cfn-lint | [iac], [iac-lint] |
| Kubernetes / host | Kubescape, kube-bench | [k8s] (binaries) |
| GenAI model files | ModelScan | [genai] |
| Cloud CSPM | Prowler (AWS), ScoutSuite (multi-cloud) | [aws], [aws-scoutsuite] |
| License | ScanCode | [license] |
| Malicious packages | GuardDog | [malpkg] |
| PII / data | Presidio | [pii] |
| Malware | YARA | [malware] |
| Provenance | Cosign (sigstore/SLSA) | [provenance] (binary) |
| SCM / CI posture | OpenSSF Scorecard | [scm] (binary) |
| DAST / web | nuclei | [web] (binary) |
| Network | nmap | [network] (binary) |
| TLS | sslyze | [tls] |
| API | schemathesis | [api] |
Still on the roadmap: mobile (MobSF), CIEM/attack-path graphs, full cross-engine OCSF export, and live-cluster runtime (Falco). The plugin contract already supports them.
Metadata
Release files for super-scanner 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| super_scanner-0.0.2.tar.gz | 108.6 kB | With provenance | Details for super_scanner-0.0.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| super_scanner-0.0.2-py3-none-any.whl | Python 3 | none | any | Details for super_scanner-0.0.2-py3-none-any.whl |
Total release size: 252.8 kB
Release files / super_scanner-0.0.2.tar.gz
| Download URL | super_scanner-0.0.2.tar.gz |
|---|---|
| Size | 108.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
da302a5eac85371f33f32ded6d22149ded0fe60ee9d670a94622891d5c3c62c0
|
|
BLAKE2b-256 checksum How to use checksums |
877e7490199d317405f5580959607a36cc3955de9da21e95659886b9eda22ca2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 8, 2026.
Transparency logRelease files / super_scanner-0.0.2-py3-none-any.whl
| Download URL | super_scanner-0.0.2-py3-none-any.whl |
|---|---|
| Size | 144.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ddf9e999a86e459bf4ceab5d7c2e67404015061eeea5eaa27b8db19600c6292b
|
|
BLAKE2b-256 checksum How to use checksums |
f227dbc6e459f0bfac769405fc5a9d091dadb345a0a62a9aa3a807b1ae24997f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 8, 2026.
Transparency logSecurity for super-scanner 0.0.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for super_scanner-0.0.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.