Skip to main content

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.db to 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 --json for 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

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

  1. Subclass BaseProvider in src/enricher/providers/
  2. Set name, supported_types, implement lookup()
  3. Instantiate it in cli.py's _build_providers()

The orchestrator, cache, and scoring engine pick it up automatically.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

threat_intel_tool-0.1.0.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

threat_intel_tool-0.1.0-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

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

Hashes for threat_intel_tool-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c621308dc8d1a02d436d1c571962334070fd64ac2c74e55f8356b3b0848ae8c6
MD5 c03c669d73aafdeab29239c6e42698d6
BLAKE2b-256 142ed46d698763aa6437b143ee11614c9256f269e5fc26aa37d232617d29c1c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for threat_intel_tool-0.1.0.tar.gz:

Publisher: publish.yml on idrak888/threat-intel-enrich

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file threat_intel_tool-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for threat_intel_tool-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7c979998184f3a9ce674e44d62459ec5483bdd4eff1a8552b80438162c8a814f
MD5 e880724dedea26ae7fb2aaa14bb1c8ed
BLAKE2b-256 172ecacfcb5263460a4fa084ebdbee5f6520c15404b6fc53c7c69df82bfbad89

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page