Skip to main content

A security-first toolkit for the full first-response threat intel workflow - triage, monitor, detonate.

Project description

Tsume (爪)

A security-first toolkit for the full first-response threat intel workflow — triage, monitor, detonate.

Inspired by malwoverview and mihari.

Install

Not published to PyPI — install from a checkout of this repo.

pip install -e "."          # CLI only
pip install -e ".[web]"     # + web dashboard (tsume web)
pip install -e ".[yara]"    # + local YARA scanning (tsume scan)
pip install -e ".[extract]" # + PDF IOC extraction (tsume extract)
pip install -e ".[report]"  # + PDF report export (tsume report)
pip install -e ".[all]"     # + everything above

yara-python requires a C compiler on platforms without a prebuilt wheel; if the install fails, tsume scan will tell you it needs the extra rather than crashing. fpdf2 (report) and pypdf (extract) are pure Python.

Working on Tsume itself? Add dev to any of the above for tests/lint/type-checking, e.g. pip install -e ".[dev,all]".

Providers

Run tsume providers for a live view of every provider, the IOC types it supports, and whether its API key is currently configured — the table below adds the env var name and quirks/rate-limit notes that don't fit in a terminal table.

Provider Env var Supports Notes
virustotal TSUME_VIRUSTOTAL_API_KEY hash, ip, url, domain default for all types
abuseipdb TSUME_ABUSEIPDB_API_KEY ip default for ip
urlhaus TSUME_URLHAUS_API_KEY hash, ip, url, domain default for hash/url/domain; requires an abuse.ch Auth-Key
malwarebazaar TSUME_MALWAREBAZAAR_API_KEY hash opt-in via --provider; requires an abuse.ch Auth-Key
threatfox TSUME_THREATFOX_API_KEY hash, ip, url, domain opt-in via --provider; requires an abuse.ch Auth-Key
shodan TSUME_SHODAN_API_KEY ip opt-in via --provider; informational (open ports/CVEs), not a malicious/clean verdict source
greynoise TSUME_GREYNOISE_API_KEY (optional) ip opt-in via --provider; Community API works without a key (10 lookups/day), a key raises the quota (up to 50/week)
hybrid-analysis TSUME_HYBRID_ANALYSIS_API_KEY hash opt-in via --provider
alienvault TSUME_ALIENVAULT_API_KEY (optional) hash, ip, url, domain opt-in via --provider; OTX general lookups work without a key
urlscanio TSUME_URLSCANIO_API_KEY ip, url, domain opt-in via --provider; anonymous search works but result detail (verdicts) needs a key
triage TSUME_TRIAGE_API_KEY hash, ip, url, domain opt-in via --provider; Hatching Triage sandbox search — matches any sample that contacted an ip/url/domain during sandbox execution, not indicators that are themselves malicious (a benign IP a piece of malware happened to resolve DNS against can come back "malicious")
ipinfo TSUME_IPINFO_API_KEY (optional) ip opt-in via --provider; informational only (org/geo/ASN), no verdict; works without a key at a lower rate limit
polyswarm TSUME_POLYSWARM_API_KEY hash, ip, url, domain opt-in via --provider; raw REST against Polyswarm's API (no SDK dependency, so it stays on the SSRF-guarded session)
whois none needed ip, domain opt-in via --provider; informational only, no verdict; RDAP over plain HTTPS (bootstrapped via rdap.org), no python-whois/ipwhois dependency
malshare TSUME_MALSHARE_API_KEY hash opt-in via --provider; response shape confirmed live
pulsedive TSUME_PULSEDIVE_API_KEY (optional) ip, url, domain opt-in via --provider; network-indicator OSINT (not hashes — Pulsedive's indicator model is network infrastructure); unauthenticated requests work at a much lower rate limit

CVE providers (tsume cve)

Provider Env var Notes
nist TSUME_NIST_API_KEY (optional) default; NVD's public API works unauthenticated at a lower rate limit
vulncheck TSUME_VULNCHECK_API_KEY opt-in via --provider; checks VulnCheck's KEV (known exploited vulnerabilities) list; response shape confirmed live
vulncheck-nvd TSUME_VULNCHECK_NVD_API_KEY opt-in via --provider; VulnCheck's NVD++ index (nist-nvd2) — a mirror of NVD data enriched with VulnCheck's own CPE matching, same CVSS-based verdict as nist; based on published API docs, not yet confirmed against a live key
vulncheck-xdb TSUME_VULNCHECK_XDB_API_KEY opt-in via --provider; VulnCheck's Exploit Database (XDB) — public proof-of-concept exploit code found for the CVE, a distinct signal from KEV (public PoC existing doesn't mean it's been used in the wild, so this never scores MALICIOUS on its own); based on published API docs, not yet confirmed against a live key

Family/actor providers (tsume family)

Provider Env var Notes
malpedia TSUME_MALPEDIA_API_KEY default; requires manual account approval from Malpedia — the free-registration flow doesn't grant API access. Response shape unconfirmed against a live key. Family names use Malpedia's own convention (e.g. win.emotet, not Emotet)
mitre-attack none needed default; enriches with MITRE ATT&CK groups/software and their techniques, entirely offline against a local dataset — run tsume attack-update first (see below)

Only the "default" providers above run when --provider is omitted, to keep a bare tsume hash <value> fast and light on API quota. Pass --provider to query any other provider — repeatable (--provider shodan --provider greynoise) or comma-separated (--provider shodan,greynoise), whichever you prefer.

These built-in defaults can be overridden per IOC type in the config file's [defaults] section (see below) — useful if you'd rather always query ThreatFox, or drop AbuseIPDB from your default IP lookups.

Configuration

API keys are read in this order:

  1. Environment variable: TSUME_<PROVIDER>_API_KEY (hyphens in the provider name become underscores, e.g. hybrid-analysisTSUME_HYBRID_ANALYSIS_API_KEY)
  2. OS keyring (service name tsume, username = provider name)
  3. ~/.tsume.conf (plaintext, last resort — a warning is printed if used)

The config file is standard INI format, one section per provider:

[virustotal]
api_key = your-key-here

[hybrid-analysis]
api_key = your-key-here

To override which providers run by default for each IOC type (instead of the built-in defaults listed above), add a [defaults] section with a comma-separated provider list per type. Any type you don't list keeps the built-in default:

[defaults]
hash = virustotal, urlhaus, threatfox
ip = abuseipdb, shodan, greynoise
url = urlhaus
domain = urlhaus

This only changes what runs when --provider is omitted — --provider on the command line always takes precedence over both the config file and the built-in defaults.

Usage

Lookups

tsume hash <md5|sha1|sha256> [--provider ...] [--format json|table] [--no-cache] [--cache-ttl SECONDS]
tsume ip <address> [--provider ...] [--format json|table] [--no-cache] [--cache-ttl SECONDS]
tsume url <url> [--provider ...] [--format json|table] [--no-cache] [--cache-ttl SECONDS]
tsume domain <domain> [--provider ...] [--format json|table] [--no-cache] [--cache-ttl SECONDS]
tsume cve <cve-id> [--provider ...] [--format json|table] [--no-cache] [--cache-ttl SECONDS]
tsume family <name> [--provider ...] [--format json|table] [--no-cache] [--cache-ttl SECONDS]

Every lookup is served from and saved to a persistent disk cache (~/.tsume_cache.db, default 1 hour TTL); --no-cache bypasses it and tsume cache-clear empties it entirely.

Batch, local file analysis, and reporting

tsume batch <file> [--type hash|ip|url|domain|cve|family] [--provider ...] [--format json|table]
tsume scan <file> --rules <rule-file-or-dir> [--format json|table]           # requires the `yara` extra
tsume extract <file.pdf|file.eml> [--type pdf|eml] [--output <file>] [--format json|table]
tsume report <output.html|output.pdf> [--ioc-type ...] [--verdict ...] [--provider ...] [--search ...] [--limit N]

batch reads one IOC per line (# comments allowed) and auto-detects each line's type unless --type forces one. extract pulls hash/IP/URL/CVE/domain-shaped strings out of a PDF or email — including "defanged" indicators like hxxp:// and 1[.]2[.]3[.]4 — and --output writes a clean line-per-IOC file ready to feed straight into batch. report exports a filtered slice of lookup history.

MITRE ATT&CK

tsume attack-update [--url <bundle-url>]     # downloads MITRE's public ATT&CK dataset (~45MB), once
tsume attack <technique-id|group-or-software-name>

attack-update fetches the STIX bundle to ~/.tsume_attack.json; nothing else in Tsume downloads it automatically. tsume attack T1055.011 looks up a technique by ID; tsume attack "Evil Corp" matches a group or software by name or alias.

Scheduled monitoring & alerting

tsume monitor add <name> --type <ioc-type> --value <value> [--provider ...] [--alert-on malicious|change] [--webhook <url>]
tsume monitor list
tsume monitor enable|disable|remove <rule-id>
tsume monitor run       # runs every enabled rule once; invoke this from cron/Task Scheduler
tsume monitor history   # shows fired alerts

A rule re-checks its IOC each time monitor run is invoked and only alerts when the outcome is new (a changed verdict, or a newly-malicious result it hadn't already recorded) — a scheduled cron job won't re-alert on an unchanged result every time it runs. --webhook POSTs a JSON payload to any URL (Slack/Discord incoming webhooks, a self-hosted relay, etc.) when a rule fires.

Triage cloud detonation

tsume detonate <file> [--network internet|drop|tor|vpn] [--timeout SECONDS] [--wait] [--yes]
tsume detonate-status <sample-id>

Uploads a local file to Triage's cloud sandbox for full dynamic analysis (not just hash reputation). Prompts for confirmation before every submission — depending on your Triage account tier, samples may be public and visible to other Triage users; Tsume reports "private"/"public"/"unknown" rather than guessing when the API doesn't say. --wait blocks and polls until reported; otherwise check back later with detonate-status.

Web dashboard

tsume web [--host 127.0.0.1] [--port 8400] [--reload] [--allow-remote]

See below.

History & the web dashboard

Every successful lookup — from the CLI or the web UI — is recorded to a local SQLite database at ~/.tsume_history.db. There's no separate opt-in: it's written automatically so the dashboard has real data to show without extra setup, and it never leaves your machine.

tsume web (requires the web extra) starts a local FastAPI server with six views:

  • History (default view) — a searchable, filterable, sortable log of every past lookup, with an expandable row showing the full raw provider response.
  • Trends — aggregate stats: verdict/severity distribution, lookups by provider and IOC type, and a list of IOCs where providers disagreed on the verdict.
  • Live Lookup — the same hash/ip/url/domain/cve/family lookups as the CLI, run from a form in the browser, streamed in per-provider over SSE as each one completes rather than waiting for the slowest one.
  • Monitor — add/list/enable/disable/remove monitor rules and trigger a manual run, plus a recent-alerts feed; the browser equivalent of tsume monitor.
  • ATT&CK — search techniques by ID or groups/software by name, same as tsume attack.
  • Tools — file-upload workflows for YARA scanning, PDF/email IOC extraction, and Triage cloud detonation.

The dashboard is entirely local — no CDN assets, no external API calls beyond the same provider APIs the CLI already talks to, and no data leaves your machine except those provider requests. Design direction lives in PRODUCT.md and DESIGN.md (a security-tool "Operator's Console" aesthetic: dark graphite surface, a single steel-cyan accent, verdict colors reserved exclusively for verdict meaning).

The dashboard has no authentication. It defaults to binding 127.0.0.1 only, which is safe — nothing off this machine can reach it. tsume web refuses to bind to any other address unless you pass --allow-remote, because several views can trigger real actions with no login prompt: Triage cloud submissions against your API quota, YARA scans, and monitor rule changes. Only use --allow-remote on a network you trust.

Development

ruff check .
mypy --strict src/tsume/core
pytest

Skipped providers

Researched against malwoverview's actual usage and ruled out entirely (not that they're bad services — they just don't fit any of Tsume's command shapes):

  • BGPView — the bgpview.io domain no longer resolves; the service appears to be shut down entirely.

Roadmap

  • v1: VirusTotal, AbuseIPDB, URLhaus lookups; validation + SSRF-guard core; tests + CI.
  • v2: 15 hash/ip/url/domain providers, cve command (NIST, VulnCheck), family command (Malpedia), persistent SQLite history, disk-backed response cache, batch processing, YARA scanning, HTML/PDF reports, and a tsume web dashboard with per-provider SSE streaming.
  • v3: MITRE ATT&CK mapping, IOC extraction from PDFs/emails, rule-based scheduled monitoring with alerting, and an expanded Triage integration (multi-IOC search, cloud detonation). A TUI dashboard was considered and deliberately dropped — the CLI and web dashboard already cover the scriptable and visual use cases, so a third UI wasn't worth the maintenance cost. LLM enrichment (summarizing multi-provider results) remains unbuilt by choice.
  • Not yet verified against a live key: Malpedia's family-lookup response shape — blocked on manual account approval, not a code issue.

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

tsume-0.1.0.tar.gz (128.5 kB view details)

Uploaded Source

Built Distribution

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

tsume-0.1.0-py3-none-any.whl (120.6 kB view details)

Uploaded Python 3

File details

Details for the file tsume-0.1.0.tar.gz.

File metadata

  • Download URL: tsume-0.1.0.tar.gz
  • Upload date:
  • Size: 128.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for tsume-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9f0fa98651ea8ba58b6b0c5a3139eb38a8f81dbed4b915221535ba212e0a851c
MD5 60e3a0dfcc54e776b54708d2e34f74aa
BLAKE2b-256 8c54305d61e54fdc00fcd472abbe14e4c92721c45447ff2d4b9bc4360491c134

See more details on using hashes here.

File details

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

File metadata

  • Download URL: tsume-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 120.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for tsume-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0002cfd6c99e97ffc0e09c21cf1434f7587edb36211e041609c995a6bc5baa00
MD5 d09e2680da821c22599f5e2dd39dcbf0
BLAKE2b-256 144daf91c623b6b0e251e76edb384890ee818abbf9c48503062bd930810aef16

See more details on using hashes here.

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