Cerberus is a fast, privacy-first command-line malware scanner for macOS and Linux. Like its three-headed namesake, it guards your machine with three detection layers: ClamAV signature scanning, built-in heuristics (executables hidden inside archives, deceptive double extensions, type/extension mismatches, autorun.inf, the EICAR test string, and unsigned or multi-format binaries via PE/ELF/Mach-O parsing), and optional VirusTotal hash lookups. It never uploads your files - VirusTotal queries send SHA-256 hashes only - and outputs clear terminal, TXT, and HTML reports. Single self-contained Rust binary, zero runtime dependencies.
Three complementary detection layers:
- ClamAV - a real signature-based antivirus engine, driven through the
clamscanbinary. If ClamAV is missing, the layer disables itself cleanly and the scan keeps going. - Built-in heuristics - per-file checks: real type vs declared extension, deceptive double extensions, executable extensions, autorun files, the EICAR test string, and unsigned executables.
- VirusTotal - SHA-256 hash lookups only (never the file contents), optional, enabled only when an API key is present.
Multi-format executable recognition via goblin: PE (Windows), ELF (Linux) and Mach-O (macOS). For PE files, the tool reports whether the binary is signed and tries to extract the signer.
Each file gets a CLEAN, SUSPECT or DANGEROUS verdict with its reasons, and the scan produces a global verdict. A progress bar and colored output accompany the scan of a large volume.
- macOS or Linux (USB mode targets volumes mounted under
/Volumeson macOS). - Rust and cargo to build.
- ClamAV (optional but recommended):
brew install clamav # macOS (or your distribution's package manager)
freshclam # downloads the signature databasegit clone <repository-url>
cd cerberus
cargo build --releaseThe binary is produced at target/release/cerberus.
cerberus --usb # detect and scan USB drives / external volumes
cerberus ~/Downloads # scan a directory
cerberus "/Volumes/My USB" # path with spaces (quoted)
cerberus file.exe # scan a single file
cerberus --interactive # interactive menuUseful options:
--no-vtforces VirusTotal off.--vtforces VirusTotal on (if a key is present in config).
With no argument, the tool launches the interactive menu (1 scan a USB drive, 2 scan a directory or a file, 3 quit).
Exit codes, handy in scripts or CI: 0 clean, 1 suspect, 2 dangerous.
Scan results
----------------------------------------
Files analyzed: 2
CLEAN: 1
SUSPECT: 0
DANGEROUS: 1
Files to review:
[DANGEROUS] /Volumes/My USB/invoice.pdf.exe
sha256: 275a021b...
- ClamAV: Eicar-Test-Signature
- deceptive double extension .pdf.exe (masking technique)
- EICAR antivirus test file
Global verdict: DANGEROUS
VirusTotal is disabled until an API key is configured.
- Create a free account at https://www.virustotal.com and grab your API key.
- Copy the example config, then paste your key:
cp config.example.toml config.toml- In
config.toml, section[virustotal], fill inapi_key.
Important reminder: only the file's SHA-256 hash is sent to VirusTotal, never its contents. Requests are limited to risky files, deduplicated by hash, spaced out (16 s by default) and capped (25 by default) to respect the free quota. If the cap is reached, the report says so explicitly.
- Scanned files are never modified, deleted or moved.
- Nothing is uploaded, except the SHA-256 hash if VirusTotal is enabled - file contents are never uploaded.
- Reports are written locally to
reports/, which is gitignored because they may contain sensitive paths and file names. config.tomlis gitignored because it may contain your API key.
For each file, the tool applies the heuristic checks, cross-references the result with ClamAV detection (a single recursive pass over the target) and, for risky files, queries VirusTotal by hash. The verdict is:
- DANGEROUS: ClamAV detection, or at least one malicious VirusTotal engine, or a serious heuristic signal (EICAR, double extension, an executable entry inside an archive).
- SUSPECT: at least one suspicious heuristic signal (executable extension, type mismatch, unsigned executable, autorun).
- CLEAN: no signal.
ZIP archives are inspected without extraction, including nested ZIPs, with guardrails against zip bombs (bounded maximum depth and cumulative decompressed size). No executable is ever written to disk.
cargo testThe tests are self-contained, with no network access: the EICAR string and a minimal unsigned PE are generated at runtime, no malicious file is committed. They run on macOS as well as Linux (GitHub Actions CI).
MIT - see the LICENSE file.