Analyse a file for malicious or risky content, combining two CIRCL engines:
- hashlookup — instant known-file triage against public catalogues (NIST NSRL, Windows builds, Linux distribution packages, CDNJS, Snap). Known-benign files resolve in milliseconds without deeper analysis.
- Pandora — deep behavioural file analysis (via pypandora) for everything the triage cannot clear.
┌────────────┐ known-benign ┌─────────┐
file ─hash─▶│ hashlookup │──────────────────▶│ INFO │
└─────┬──────┘ (short-circuit) └─────────┘
│ unknown / single-source / offensive-distro / known-malicious
▼
┌────────────┐ ALERT→CRITICAL WARN→HIGH
│ Pandora │──────────────────────────────▶ verdict
└────────────┘ CLEAN→LOW timeout→MEDIUM
(known-malicious hits are escalated —
CLEAN→MEDIUM, timeout/skipped→HIGH)
A hashlookup hit means the file is catalogued, not that it is safe. The short-circuit therefore only fires when both hold:
hashlookup:trustis strictly above 50 — the file appears in more than one independent source (50 means "no opinion", a single source);- the source is not an offensive distribution (Kali, BlackArch) — their packages (password crackers, lateral-movement tooling) are catalogued but still deserve deep analysis.
Records carrying a KnownMalicious marker never short-circuit either — but
the marker is not a verdict. Per CIRCL, it is a raw pointer to
malware-corpus sources (malshare et al. explicitly disclaim their feeds), and
stock Windows files such as calc.exe carry it because malware bundles them.
A flagged file is therefore forced through Pandora deep analysis and the
analysis result drives the severity: ALERT→CRITICAL (corroborated),
WARN→HIGH, CLEAN→MEDIUM ("analyst review advised"), and HIGH whenever the
analysis is skipped or inconclusive. Note that this means flagged files are
uploaded to the configured Pandora instance; when handling sensitive
content, point --pandora-url at an internal instance or use --no-pandora.
Both knobs live in fileanalyzer/constants.py (TRUST_THRESHOLD,
OFFENSIVE_SOURCE_MARKERS). The full hashlookup context (trust, source,
catalogued filename) is always shown in the report, so short-circuited
verdicts remain auditable.
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"fileanalyzer check suspicious.pdf # full pipeline
fileanalyzer check sample.exe --no-pandora # triage-only mode
fileanalyzer check sample.exe --json # machine-readable output
fileanalyzer check sample.exe --output report.html # export (.txt/.svg/.html)
fileanalyzer check sample.exe --pandora-url https://pandora.internal/
fileanalyzer info verdicts # verdict mapping + policy
fileanalyzer info engines # live engine status
fileanalyzer --versionThe Pandora instance defaults to https://pandora.circl.lu/ and can be
overridden with --pandora-url or the FILEANALYZER_PANDORA_URL environment
variable.
| Code | Meaning |
|---|---|
| 0 | File is clean (verdict INFO or LOW) |
| 1 | Risky file (MEDIUM/HIGH/CRITICAL) or invalid input |
| 2 | Network / engine error (hashlookup or Pandora unreachable) |
| Severity | Meaning |
|---|---|
| CRITICAL | Pandora ALERT (incl. corroborated known-malicious hashes) |
| HIGH | Pandora WARN, or a known-malicious hash Pandora could not clear |
| MEDIUM | Analysis inconclusive (timeout/error) or skipped for an unknown file; known-malicious hash with CLEAN analysis (analyst review) |
| LOW | Pandora CLEAN — no detection, file not in the known DB |
| INFO | Known benign file — hashlookup short-circuit |
from fileanalyzer.assessor import assess
report = assess("suspicious.pdf")
print(report.verdict) # VerdictSeverity.LOW
print(report.triage.reason) # triage explanation
if report.analysis:
print(report.analysis.link) # Pandora report URLpython -m pytest # full suite with coverage
python -m pytest --tb=short -qThe test suite has 88 tests with 100% coverage. All network I/O is mocked
at the hashlookup_utils / pandora_utils boundaries — no live calls.
GPL-3.0 — see LICENSE.