CLI tool for enriching security indicators against multiple threat intelligence sources
Project description
threat-intel-enrich
A CLI tool for security analysts. Give it an IP, domain, or file hash — get back a consolidated risk verdict with a confidence score, queried from multiple threat intel sources in parallel.
$ enrich 185.220.101.34
╭─────────────────────────────────────────────────╮
│ Threat Intel Report: 185.220.101.34 │
│ Type: Ip │
│ │
│ Risk Score: 8.4 / 10 — CRITICAL │
│ │
│ Virustotal: malicious (12/87 engines) │
│ Abuseipdb: reported 247 times (score: 95) │
│ │
│ Tags: tor-exit-node, data-center/web-hosting │
│ │
│ Links: │
│ • Virustotal: https://virustotal.com/gui/... │
│ • Abuseipdb: https://abuseipdb.com/check/… │
╰─────────────────────────────────────────────────╯
Features
- Parallel queries — all providers are called concurrently via
asyncio - Auto-detection — IPv4, IPv6, domains, MD5, SHA1, SHA256 are detected automatically
- SQLite cache — responses cached at
~/.enricher/cache.dbto respect rate limits (TTL: 1 hour by default) - Weighted scoring — VirusTotal (60%) + AbuseIPDB (40%) produce a single 0–10 risk score
- Rich terminal output — colour-coded panel or
--jsonfor piping into other tools - Graceful degradation — missing API keys or provider errors skip that source; the tool continues with the rest
Architecture
┌─────────────────────────────────────────────────────┐
│ CLI (cli.py) │
│ click command → detect indicator → call enrich() │
└───────────────────────┬─────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Orchestrator (core/enrich.py) │
│ │
│ asyncio.gather() ──► provider_1.lookup() │
│ └──► provider_2.lookup() │
│ │
│ Each call wrapped with cache read/write │
└──────┬────────────────────────┬────────────────────-┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ VirusTotal │ │ AbuseIPDB │
│ (API v3) │ │ (API v2) │
│ │ │ IP only │
└──────┬──────┘ └───────┬─────────┘
│ │
└──────────┬────────────┘
│ list[ProviderFinding]
▼
┌─────────────────────────────────────────────────────┐
│ Scoring (core/scoring.py) │
│ │
│ weighted_sum = Σ confidence × provider_weight │
│ risk_score = (weighted_sum / total_weight) × 10 │
│ │
│ Weights: virustotal=0.6 abuseipdb=0.4 │
└──────────────────────┬──────────────────────────────┘
│ Verdict
▼
Rich panel / JSON output
Cache layer (cache/sqlite.py)
~/.enricher/cache.db
key = {provider}:{indicator_type}:{indicator_value}
TTL = ENRICHER_CACHE_TTL (default 3600 s)
Module map
src/enricher/
├── cli.py Click entrypoint, Rich rendering
├── config.py pydantic-settings — loads .env
├── core/
│ ├── models.py Indicator, ProviderFinding, Verdict (Pydantic)
│ ├── enrich.py Orchestrator — parallel fan-out + cache
│ └── scoring.py Weighted score, risk level, summary line
├── providers/
│ ├── base.py BaseProvider ABC
│ ├── virustotal.py VirusTotal API v3 (IP, domain, hash)
│ └── abuseipdb.py AbuseIPDB API v2 (IP only)
├── cache/
│ └── sqlite.py Async SQLite cache with TTL
└── utils/
└── indicators.py Indicator type auto-detection
Installation
Requires Python 3.11+.
git clone <repo>
cd threat-intel-enrich
pip install -e .
For development (linting + tests):
pip install -e ".[dev]"
Configuration
Copy .env.example to .env and fill in your keys:
cp .env.example .env
VIRUSTOTAL_API_KEY=your_key_here
ABUSEIPDB_API_KEY=your_key_here
ENRICHER_CACHE_TTL=3600
- VirusTotal free key: https://www.virustotal.com/gui/join-us (4 req/min)
- AbuseIPDB free key: https://www.abuseipdb.com/account/api (1 000 checks/day)
The tool works with just one key configured — it warns about the missing provider and continues.
Usage
# Enrich an IP address
enrich 185.220.101.34
# Enrich a domain
enrich malware-c2.example.com
# Enrich a file hash (MD5 / SHA1 / SHA256)
enrich 44d88612fea8a8f36de82e1278abb02f
# Skip cache (force fresh queries)
enrich 185.220.101.34 --no-cache
# Machine-readable JSON output
enrich 185.220.101.34 --json
# Per-provider detail breakdown
enrich 185.220.101.34 --verbose
Example outputs
Default (Rich panel)
╭──────────────────────────────────────────────────────╮
│ Threat Intel Report: 44d88612fea8a8f36de82e1278abb02f│
│ Type: Hash Md5 │
│ │
│ Risk Score: 6.0 / 10 — HIGH │
│ │
│ Virustotal: malicious (43/70 engines) │
│ │
│ Tags: trojan, ransomware │
│ │
│ Links: │
│ • Virustotal: https://virustotal.com/gui/file/... │
╰──────────────────────────────────────────────────────╯
--json
{
"indicator": {
"value": "44d88612fea8a8f36de82e1278abb02f",
"type": "hash_md5"
},
"risk_score": 6.0,
"risk_level": "high",
"findings": [
{
"provider": "virustotal",
"malicious": true,
"confidence": 0.614,
"details": {
"malicious_count": 43,
"harmless_count": 0,
"suspicious_count": 2,
"undetected_count": 25,
"total_engines": 70,
"reputation": -50
},
"tags": ["trojan", "ransomware"],
"reference_url": "https://www.virustotal.com/gui/file/44d88612fea8a8f36de82e1278abb02f"
}
],
"summary": "High risk (6.0/10) — flagged as malicious by VirusTotal (43/70 engines)",
"cached": false,
"queried_at": "2026-04-03T10:22:01.456Z"
}
Risk Score Reference
| Score | Level |
|---|---|
| 0–1.0 | clean |
| 1.1–3.0 | low |
| 3.1–5.0 | medium |
| 5.1–7.0 | high |
| 7.1–10 | critical |
Running Tests
pytest
All provider tests use mocked HTTP responses (aioresponses) — no live API calls.
Adding a Provider
- Subclass
BaseProviderinsrc/enricher/providers/ - Set
name,supported_types, implementlookup() - Instantiate it in
cli.py's_build_providers()
The orchestrator, cache, and scoring engine pick it up automatically.
Project details
Release history Release notifications | RSS feed
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 threat_intel_tool-0.1.0.tar.gz.
File metadata
- Download URL: threat_intel_tool-0.1.0.tar.gz
- Upload date:
- Size: 16.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c621308dc8d1a02d436d1c571962334070fd64ac2c74e55f8356b3b0848ae8c6
|
|
| MD5 |
c03c669d73aafdeab29239c6e42698d6
|
|
| BLAKE2b-256 |
142ed46d698763aa6437b143ee11614c9256f269e5fc26aa37d232617d29c1c3
|
Provenance
The following attestation bundles were made for threat_intel_tool-0.1.0.tar.gz:
Publisher:
publish.yml on idrak888/threat-intel-enrich
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
threat_intel_tool-0.1.0.tar.gz -
Subject digest:
c621308dc8d1a02d436d1c571962334070fd64ac2c74e55f8356b3b0848ae8c6 - Sigstore transparency entry: 1238444342
- Sigstore integration time:
-
Permalink:
idrak888/threat-intel-enrich@344cfd8321886cd740f891c75648cf620c994446 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/idrak888
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@344cfd8321886cd740f891c75648cf620c994446 -
Trigger Event:
push
-
Statement type:
File details
Details for the file threat_intel_tool-0.1.0-py3-none-any.whl.
File metadata
- Download URL: threat_intel_tool-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c979998184f3a9ce674e44d62459ec5483bdd4eff1a8552b80438162c8a814f
|
|
| MD5 |
e880724dedea26ae7fb2aaa14bb1c8ed
|
|
| BLAKE2b-256 |
172ecacfcb5263460a4fa084ebdbee5f6520c15404b6fc53c7c69df82bfbad89
|
Provenance
The following attestation bundles were made for threat_intel_tool-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on idrak888/threat-intel-enrich
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
threat_intel_tool-0.1.0-py3-none-any.whl -
Subject digest:
7c979998184f3a9ce674e44d62459ec5483bdd4eff1a8552b80438162c8a814f - Sigstore transparency entry: 1238444365
- Sigstore integration time:
-
Permalink:
idrak888/threat-intel-enrich@344cfd8321886cd740f891c75648cf620c994446 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/idrak888
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@344cfd8321886cd740f891c75648cf620c994446 -
Trigger Event:
push
-
Statement type: