Skip to main content

mwdb-cli

mwdb-cli

CLI and Python client covering the full MWDB Core API (all 122 operations)

PyPI Version Python Versions License SARIF TOON

GitHub Stars GitHub Issues Buy Me a Coffee


Overview

mwdb-cli is a Python toolkit to work with MWDB Core (CERT.pl's malware database) from the command line or as a library. It covers every operation of the MWDB Core API — all 122 operations of spec 2.18.0 — with an async-native core, a synchronous facade, and machine-readable outputs including JSON, TOON and SARIF 2.1.0.

Key Features

Feature Description
Full API coverage All 122 operations of MWDB Core 2.18.0, enforced by a spec regression test
Async + sync Async-native client with a synchronous facade over the same implementation
Multi-format output Rich tables, JSON, TOON, and SARIF 2.1.0
Typed models Dataclasses for files, configs, blobs and objects, keeping the full raw payload
Concurrent transfers Bulk downloads with --jobs; blocking I/O offloaded to threads
Resilient transport Automatic retry/backoff on 429/5xx and typed exceptions
CLI + Library Use the mwdb command or import the Python package
100% tested Live tests against a real MWDB instance (no mocks), 100% coverage

Supported Outputs

Object data     JSON, TOON
Listings        Rich tables, JSON, TOON, SARIF 2.1.0
Findings        SARIF 2.1.0 (samples/objects as results)
Downloads       Streamed files, concurrent (--jobs)

Installation

From PyPI (Recommended)

pip install mwdb-cli

From Source

git clone https://github.com/seifreed/mwdb-cli.git
cd mwdb-cli
python3 -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install -e . --group dev

Configuration

Settings resolve in order: CLI flags / constructor arguments → environment → config file → defaults.

export MWDB_URL="https://mwdb.cert.pl"     # default
export MWDB_API_KEY="<your API key>"

or ~/.mwdb.toml:

[mwdb]
url = "https://mwdb.cert.pl"
api_key = "<your API key>"

Quick Start

# Ping the server
mwdb server ping

# List the ten most recent samples
mwdb file list --count 10

# Export search results as a SARIF 2.1.0 document
mwdb --format sarif search 'tag:emotet' > results.sarif

Usage

Command Line Interface

mwdb file get <sha256>
mwdb search 'tag:emotet AND file.size:[* TO 500000]'
mwdb file download <sha256> <sha256> ... --jobs 8 -o samples/
mwdb file download <sha256> --zip -o samples/
mwdb file upload sample.bin --tags my-tag --share-3rd-party false
mwdb tag add <sha256> my-tag
mwdb comment add <sha256> "packed with UPX"
mwdb config list --query 'config.family:emotet'
mwdb attribute add <sha256> source '{"feed": "honeypot"}'
mwdb --json file get <sha256> | jq .tags

Every API area has a command group: file, config, blob, object, tag, comment, attribute, share, relation, karton, quick-query, auth, user, api-key, group, attribute-def, metakey, oauth, remote, server, plus top-level search. Run mwdb <group> --help for the operations in each group.

Global options: --url, --api-key, --config, --format, --json.

Output Formats

--format selects how results are rendered (default: table):

Option Description
--format table Human-readable rich tables (default)
--format json Pretty JSON (--json is a backward-compatible alias)
--format toon TOON: compact, token-efficient for LLMs
--format sarif SARIF 2.1.0 findings
mwdb --format toon file list           # tabular TOON block
mwdb --format sarif file list          # SARIF 2.1.0 document
mwdb --json file get <sha256>          # same as --format json

SARIF is a findings schema, so it is available only for commands that return samples or objects (file/config/blob/object list and get, and search). Each object becomes one SARIF result (artifact = sha256, ruleId = family/tag/type). Other commands report SARIF output is not available for this command.


Python Library

Async

import asyncio
from pathlib import Path
from mwdb_cli import AsyncMwdbClient

async def main() -> None:
    async with AsyncMwdbClient() as client:  # settings from env/config file
        async for sample in client.files.iterate(query="tag:emotet"):
            print(sample.sha256, sample.file_name)
            await client.files.download(sample.id, Path(sample.id))
            break

asyncio.run(main())

Sync

from mwdb_cli import MwdbClient

with MwdbClient() as client:  # same API surface, runs the async core internally
    for sample in client.files.iterate(query="tag:emotet", chunk_size=50):
        print(sample.sha256)
    stats = client.configs.stats()

Concurrent bulk work

from pathlib import Path
from mwdb_cli import AsyncMwdbClient
from mwdb_cli.bulk import run_limited

async def bulk(client: AsyncMwdbClient) -> None:
    hashes = [f.id async for f in client.files.iterate(query="tag:emotet")]
    await run_limited(
        [lambda h=h: client.files.download(h, Path(h)) for h in hashes],
        limit=8,
    )

TOON and SARIF encoders

from mwdb_cli import sarif, toon, MwdbClient

with MwdbClient() as client:
    samples = client.files.list(query="tag:emotet", count=20)

print(toon.encode([s.raw for s in samples]))     # compact TOON
if sarif.is_supported(samples):
    document = sarif.encode(samples)              # SARIF 2.1.0 dict

Errors are typed: AuthError, ForbiddenError, NotFoundError, ValidationError, ConflictError, RateLimitError, ServerError, MwdbConnectionError — all subclasses of MwdbError. Rate-limited and transient 5xx responses are retried automatically with backoff.


Development

Quality gates (all must pass clean, with no suppressions):

black --check . && ruff check . && mypy .
bandit -r -c pyproject.toml . && pip-audit
MWDB_API_KEY=<key> pytest        # live suite, 100% coverage enforced

The test suite talks to a real MWDB instance (no mocks): read operations run for real; mutating admin operations are exercised against requests the server rejects (missing capability → 403, nonexistent object → 404), so production data is never modified. Transport edge cases (retries, malformed bodies) run against a real in-process HTTP server.


Requirements

  • Python 3.14+
  • Runtime dependencies: httpx, click, rich
  • See pyproject.toml for the full list

Contributing

Contributions are welcome.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Support the Project

If this project is useful in your workflows, you can support development:

Buy Me A Coffee

License

This project is licensed under the MIT license. See LICENSE.

Attribution


Built for practical malware triage and threat-intelligence automation

Download files

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

Source Distribution

mwdb_cli-0.1.0.tar.gz (41.6 kB view details)

Uploaded Source

Built Distribution

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

mwdb_cli-0.1.0-py3-none-any.whl (33.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mwdb_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 41.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mwdb_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 870535c24aaa3bc2b80b18aaa9236677aa5d132aec0e7f643c2d21c7f83dbfe6
MD5 6a6b54c8e9951632ec0fe8c449ea823e
BLAKE2b-256 b7c7cb483fabc40cbdb943b9ec29d9030567318f5f521197d39cff2dc5e05328

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on seifreed/mwdb-cli

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

File details

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

File metadata

  • Download URL: mwdb_cli-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 33.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mwdb_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9bc617fac95285d935585860b3114d1fc5942795ed12ec5be39181fc5978a310
MD5 b49941c38b63639ad51ca3708487f4b2
BLAKE2b-256 3ce5e61f0a2bad35682b1ef9eb8627fa1501f4ae1037f9735ed5e4c04f4b2c37

See more details on using hashes here.

Provenance

The following attestation bundles were made for mwdb_cli-0.1.0-py3-none-any.whl:

Publisher: publish.yml on seifreed/mwdb-cli

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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

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