Skip to main content

vex logo

vex

IOC enrichment hub for SOC triage and DFIR — VirusTotal + AbuseIPDB / Shodan / WHOIS / MISP / OpenCTI, straight from your terminal.

 ██╗   ██╗███████╗██╗  ██╗
 ██║   ██║██╔════╝╚██╗██╔╝
 ██║   ██║█████╗   ╚███╔╝
 ╚██╗ ██╔╝██╔══╝   ██╔██╗
  ╚████╔╝ ███████╗██╔╝ ██╗
   ╚═══╝  ╚══════╝╚═╝  ╚═╝

PyPI Python License


vex takes an indicator (a hash, IP, domain, or URL) and turns it into a verdict with context. It started as a VirusTotal CLI and grew into an enrichment hub: one primary source (VirusTotal) plus optional secondary sources that add reputation and your own threat-intel. It runs standalone, and it slots into a pipeline (barb → vex → sift) over stdin/stdout.

[!NOTE] Current release: vex 1.6.1 (on PyPI). On main (pending 1.7.0): TI write-back, watchlist run, daily VT-quota counter, --version flag. Full manual: docs/.

Install

pip install vex-ioc          # core
pip install vex-ioc[ai]      # + Anthropic / OpenAI explanations (Ollama needs no extra)

Quickstart

vex config --set-api-key YOUR_VT_KEY     # or set VT_API_KEY
vex triage 8.8.8.8
vex triage evil.com --explain            # add an AI narrative
vex investigate <sha256> -o rich         # deep dive
IOC: 8.8.8.8 (ipv4)
Verdict: CLEAN
Detections: 0 malicious / 0 suspicious / 94 engines
Reputation: 0

What you get

  • Two modestriage (fast verdict, minimal API calls) and investigate (deep DFIR: PE info, sandbox behavior, passive DNS, relationships, MITRE ATT&CK, timeline).
  • Multi-source enrichment — VirusTotal primary; AbuseIPDB, Shodan, WHOIS, MISP, and OpenCTI as secondary enrichers (key-gated, fail-open).
  • Batch correlation--correlate clusters a batch of IOCs by shared infrastructure (ASN, malware family, contacted IPs/domains).
  • AI explanations — opt-in --explain narratives (Claude / OpenAI / local Ollama / deterministic template), with prompt-injection defense on the untrusted data fed to the model.
  • Pipeline-ready output — JSON, NDJSON (streaming), CSV, STIX 2.1, ATT&CK Navigator, self-contained HTML; verdict-mapped exit codes.
  • Quota-aware batches — IOC dedup, an up-front ETA, a --max-quota budget guard, and a persistent daily VT-quota counter with a stderr status line (on main, pending 1.7.0).
  • Local knowledge basevex tag / note / watchlist annotate IOCs in ~/.vex/. Re-triage an entire watchlist in one shot with vex watchlist run <name> (on main, pending 1.7.0).
  • TI write-back (on main, pending 1.7.0)vex investigate --sight writes MISP sightings and OpenCTI observables for IOCs above a configurable verdict floor; triple opt-in (config killswitch + flag + dry-run preview).

Verdicts

Verdict Meaning
🟢 CLEAN No engine flagged it.
🟡 UNKNOWN Not enough data, or the IOC was not found.
🟠 SUSPICIOUS Low-confidence detections.
🔴 MALICIOUS Meets the malicious-detection threshold.

Enrichment sources

VirusTotal is the primary source; it produces the verdict. The others are secondary enrichers that augment an investigate result.

Source IOC types Enable via
VirusTotal all VT_API_KEY / --api-key / vex config
AbuseIPDB IP VEX_ABUSEIPDB_API_KEY
Shodan IP VEX_SHODAN_API_KEY
WHOIS domain core (no key)
MISP all MISP_URL + MISP_API_KEY
OpenCTI all OPENCTI_URL + OPENCTI_TOKEN

[!IMPORTANT] Secondary enrichers run on investigate only, not triage (triage stays fast). Each is no-op without its key, fail-open (a failure or timeout never blocks the run), and they run concurrently. Run vex doctor --probe to see which are configured and reachable.

Correlation

vex triage -f iocs.txt --correlate            # deterministic cluster table
vex triage -f iocs.txt --correlate --explain  # + per-cluster AI campaign narrative

--correlate groups a batch by shared ASN, malware family, contacted IPs, and contacted domains — surfacing likely campaigns. It is deterministic by default; the AI narrative is added only when --explain is also set.

AI explanations

--explain adds a narrative and next steps; --explain-model overrides the model. Providers: Anthropic, OpenAI, local Ollama, and a deterministic template fallback when none is configured.

export VEX_AI_PROVIDER=ollama        # local, no cloud key
vex investigate evil.com --explain

[!WARNING] Enrichment data (sandbox strings, file names, family labels) is attacker-influenceable. Before it reaches an LLM, vex scans it for prompt-injection patterns and redacts critical attempts, and the system prompt instructs the model to treat the data as untrusted. This is defense-in-depth, not a guarantee.

Output formats

-o rich (default TTY) · -o console · -o json · -o ndjson (one result per line, streamed) · --csv · --stix · --navigator (ATT&CK layer, investigate) · --html <path> (self-contained report). All formats show real IOCs by default; --defang defangs them (e.g. evil[.]com); HTML reports always defang.

sift triage alerts.json -o json | vex triage --from-sift -o ndjson

Pipeline

flowchart LR
    barb -->|URLs / IOCs| vex
    vex -->|enriched IOCs| sift
    sift -.->|extracted IOCs| vex

vex is the enrichment hub. --from-barb reads barb JSON; --from-sift reads a sift TriageReport, extracts its IOCs, and enriches them — closing the sift ↔ vex loop. NDJSON output and verdict exit codes make it scriptable downstream.

Scale

For large batches, such as IOCs extracted from a SIEM export:

  • Dedup — duplicate IOCs are collapsed before any query, which saves quota; --no-dedup disables it.
  • ETA + counters — an up-front estimate and a processed (N from API, M cached) summary on stderr.
  • --max-quota N — caps fresh API lookups; cached IOCs are still served, the rest are skipped with a notice. Re-run to continue — the SQLite cache resumes where you left off.

Configuration

Priority: --api-key flag → environment variable → ~/.vex/config.yaml → defaults.

vex config --show        # active config, masked secrets
vex doctor               # what's configured (no network)
vex doctor --probe       # + live connectivity, surfaces the actual error
Variable Purpose
VT_API_KEY VirusTotal
VEX_AI_API_KEY / VEX_AI_PROVIDER / VEX_AI_MODEL AI provider
VEX_ABUSEIPDB_API_KEY AbuseIPDB enricher
VEX_SHODAN_API_KEY Shodan enricher
MISP_URL / MISP_API_KEY MISP lookup
OPENCTI_URL / OPENCTI_TOKEN OpenCTI lookup

enrichment.stix_tlp_version (1.0 default, 2.0) selects which STIX TLP marking ids the export emits.

TI write-back (on main — pending 1.7.0)

vex investigate --sight writes MISP sightings and OpenCTI observables back for IOCs that meet a configurable verdict floor. Three gates must all be open before any write occurs:

  1. enrichment.writeback_enabled: true in ~/.vex/config.yaml (default false).
  2. --sight flag on vex investigate.
  3. Use --dry-run-sight first to preview the payloads without sending.
vex investigate 1.2.3.4 --dry-run-sight     # preview payloads, no network
vex investigate 1.2.3.4 --sight             # write if enabled and above floor
vex investigate -f iocs.txt --sight         # batch write-back

[!IMPORTANT] Before using --sight against a real OpenCTI instance, run --dry-run-sight, review the payload, then confirm one MISP sighting and one OpenCTI observable in the UI. The GraphQL mutation (stixCyberObservableAdd) works for network observables on OpenCTI ≥ 5.x; file-hash observables may need a different shape on some versions. Verify against your instance. See vex manual writeback.

Key config keys (in enrichment: section):

Key Default Meaning
writeback_enabled false Master switch — must be true or --sight is a no-op.
writeback_tlp "green" TLP ceiling. Writes are blocked when the IOC's source TLP is more restrictive.
writeback_min_verdict "SUSPICIOUS" Verdict floor — IOCs below this are silently skipped.

Security

[!WARNING]

  • Secondary enrichers (AbuseIPDB / Shodan / WHOIS / MISP / OpenCTI) fail-open — never block a run — and are no-op without a key.
  • The VT API key is never hard-coded — env var, config, or --api-key.
  • Premium calls are gated behind config.is_premium; the free tier is never broken.
  • Restricted TI: TLP/markings are carried through; marked intel is never emitted unmarked.
  • Write-back is inert by default (writeback_enabled: false). Credentials for MISP and OpenCTI are stored only in ~/.vex/config.yaml (0o600) or environment variables — never in CLI arguments or logs.
  • Machine output stays clean — all notices go to stderr, not stdout.

Exit codes

Computed from the highest-severity verdict in the run:

Code Meaning
0 CLEAN / UNKNOWN
1 SUSPICIOUS — or a runtime error / bad input
2 MALICIOUS

Known limitations

  • MISP (v2.5.38) and OpenCTI (demo v7.26) lookups are live-verified end-to-end, and both have mock tests. They query real instances and stay version-sensitive: if a server's schema differs, the enricher fails open (no enrichment, no crash). Use vex doctor --probe to confirm connectivity. pycti is a possible future fallback if OpenCTI's GraphQL schema drifts.
  • AI: Anthropic and Ollama are live-verified end-to-end; OpenAI shares the same code path (mock-tested). Without a provider, --explain falls back to a deterministic template.
  • Secondary enrichers run on investigate, not triage. A triage --explain gets no AbuseIPDB / Shodan / MISP / OpenCTI context by design.
  • STIX TLP:CLEAR maps to the TLP 1.0 WHITE marking id by default — set enrichment.stix_tlp_version: "2.0" to switch to TLP 2.0 ids.
  • The VirusTotal free tier allows roughly 4 requests/min, so large batches are quota-bound — see Scale.

Docs

Full manual: docs/ — getting started, every command/flag, the enrichment model, output formats, the barb/sift pipeline contracts, and configuration. Built-in guide: vex manual (and vex manual ai / pipeline / config). Changelog: CHANGELOG.md.

Author

Christian Huhn — building security tooling for SOC/DFIR workflows.

License

MIT

Download files

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

Source Distribution

vex_ioc-1.7.2.tar.gz (191.4 kB view details)

Uploaded Source

Built Distribution

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

vex_ioc-1.7.2-py3-none-any.whl (124.3 kB view details)

Uploaded Python 3

File details

Details for the file vex_ioc-1.7.2.tar.gz.

File metadata

  • Download URL: vex_ioc-1.7.2.tar.gz
  • Upload date:
  • Size: 191.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for vex_ioc-1.7.2.tar.gz
Algorithm Hash digest
SHA256 8d2955b1aab06c2d15cdf2c31fde83a38b7b4f21e9e485284162bf6940581782
MD5 11bd5f0684b5ad0df046f0da22e8b381
BLAKE2b-256 b775ca7a7835c16ad448280f088c7a9a9f2add73a6a80337cb5a1e1ea2c92614

See more details on using hashes here.

Provenance

The following attestation bundles were made for vex_ioc-1.7.2.tar.gz:

Publisher: publish.yml on duathron/vex

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

File details

Details for the file vex_ioc-1.7.2-py3-none-any.whl.

File metadata

  • Download URL: vex_ioc-1.7.2-py3-none-any.whl
  • Upload date:
  • Size: 124.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for vex_ioc-1.7.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7134b2a19f42a33476d8892e5bd5f0654aa2a2cb3d5fb6280f4ae07f8501210d
MD5 82cc6e357bca5aad5e8430ba0bf0191b
BLAKE2b-256 8e030324f0ac34650bf39dc40a725fd2739d0932e0b2fe3cd1acfbf248e39ef0

See more details on using hashes here.

Provenance

The following attestation bundles were made for vex_ioc-1.7.2-py3-none-any.whl:

Publisher: publish.yml on duathron/vex

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

Release history Release notifications | RSS feed

1.8.1

2 files

1.8.0

2 files

This release

1.7.2 This release

2 files

1.7.1

2 files

1.7.0

2 files

1.6.1

2 files

1.6.0

2 files

1.5.1

2 files

1.5.0

2 files

1.4.0

2 files

1.2.1

2 files

1.2.0

2 files

1.1.1

2 files

1.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page