Skip to main content

Python SDK for the Threat.Zone malware analysis platform

Project description

Threat.Zone Python SDK

Official Python SDK for the Threat.Zone malware analysis platform. Targets the Threat.Zone Public API 1.0.0-rc1 surface, ships fully typed Pydantic v2 models for every endpoint, and exposes both synchronous (ThreatZone) and asynchronous (AsyncThreatZone) clients with identical method surfaces. Requires Python 3.10+.

Install

pip install threatzone
# or
uv add threatzone

Configure

from threatzone import ThreatZone

client = ThreatZone(api_key="<your-api-key>")

The client reads THREATZONE_API_KEY from the environment, so ThreatZone() is enough if you export it. The default base_url is https://app.threat.zone/public-api.

For on-prem or local development, pass base_url explicitly:

client = ThreatZone(
    api_key="<your-api-key>",
    base_url="https://threatzone.your-company.internal/public-api",
)

The base_url must include the /public-api suffix. For self-signed certs, leave verify_ssl=False (the default).

Quick usage

from pathlib import Path

account = client.get_user_info()
print(f"Workspace: {account.workspace_name}")

submission = client.create_sandbox_submission(Path("./sample.exe"))
completed = client.wait_for_completion(submission.uuid, timeout=600)
print(f"Verdict: {completed.level}")
print(f"MITRE techniques: {completed.mitre_techniques}")

Core concepts

  • Submissions — one analysis target (file or URL) with a stable uuid, a workspace owner, a private flag, and up to four reports.
  • Reportsdynamic, static, cdr, url_analysis. Independent; poll each via submission.is_complete() / submission.has_errors(). Every report carries its own status, level, score.
  • Observation streams — the dynamic report produces indicators (rule hits), iocs (concrete IOC values), behaviours (OS-level operations — the os query param is required), and syscalls (raw log lines).
  • Artifacts — files produced or extracted during analysis; keyed by hashes.sha256.
  • Access control — public submissions are visible to every API key; private submissions are workspace-scoped. Cross-workspace reads of private submissions raise PermissionDeniedError (403).

Async

AsyncThreatZone mirrors ThreatZone method-for-method:

import asyncio
from threatzone import AsyncThreatZone

async def main() -> None:
    async with AsyncThreatZone(api_key="<your-api-key>") as client:
        account = await client.get_user_info()
        print(account.email)

asyncio.run(main())

Use asyncio.gather() for concurrent fan-out. See recipe 10.

Errors

Every error inherits from ThreatZoneError. HTTP errors additionally inherit from APIError and carry the parsed error envelope on .body, with the structured code at .body["code"]. Branch on .code, never on .message.

Status Exception When
ThreatZoneError Base class. Catch for a single safety net.
APIError HTTP error base class. .status_code, .body, .response.
400 BadRequestError INVALID_UUID, INVALID_QUERY_PARAM.
401 AuthenticationError Missing/invalid API key.
402 PaymentRequiredError Workspace subscription inactive.
403 PermissionDeniedError Cross-workspace private read, or module not enabled.
404 NotFoundError Submission, artifact, or media missing.
409 ReportUnavailableError Required report not yet available. Carries .code, .submission_uuid, .required_report, .current_status, .available_reports.
429 RateLimitError API quota exceeded. Has .retry_after.
5xx InternalServerError Server-side failure.
TimeoutError HTTP request timed out.
ConnectionError Network-level failure.
AnalysisTimeoutError wait_for_completion() exceeded its timeout. .uuid, .elapsed.
202 YaraRulePendingError YARA rule generation still in progress. .retry_after.
from threatzone import ReportUnavailableError, ThreatZone

try:
    indicators = client.get_indicators("00000000-0000-0000-0000-000000000000")
except ReportUnavailableError as exc:
    if exc.code == "DYNAMIC_REPORT_UNAVAILABLE":
        print(f"Dynamic report not ready (status: {exc.current_status}).")

See recipe 9 for the full discrimination pattern and recipe 7 for the recommended retry loop.

Documentation

Document Purpose
Recipes 12 runnable examples covering common tasks.
Type Reference Pydantic model overview grouped by feature area.

Testing utilities

The SDK ships a stateful in-process fake Threat.Zone API for consumer-side tests:

from threatzone import ThreatZone
from threatzone.testing import FakeThreatZoneAPI, scenarios

fake = FakeThreatZoneAPI()
scenarios.seed_malicious_pe(fake, sha256="a" * 64)

client = ThreatZone(
    api_key="test-key",
    base_url="https://fake.threat.zone/public-api",
    http_client=fake.as_httpx_client(),
)

Available scenarios: seed_malicious_pe, seed_benign_document, seed_cdr_document, seed_phishing_url, seed_static_only_submission, seed_private_cross_workspace.

Development

uv sync --all-extras --dev
uv run pytest tests/
uv run ruff check src/ tests/
uv run mypy src/threatzone
uv build

All tests run in-process against FakeThreatZoneAPI — no network, no API token. Live smoke-testing uses the scripts in examples/ with PUBLIC_API_TOKEN exported; see examples/README.md.

GitHub Actions workflows can be exercised locally via act — see .github/workflows/README.md.

Links

License

MIT — see LICENSE.

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

threatzone-1.0.0.tar.gz (151.3 kB view details)

Uploaded Source

Built Distribution

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

threatzone-1.0.0-py3-none-any.whl (62.5 kB view details)

Uploaded Python 3

File details

Details for the file threatzone-1.0.0.tar.gz.

File metadata

  • Download URL: threatzone-1.0.0.tar.gz
  • Upload date:
  • Size: 151.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for threatzone-1.0.0.tar.gz
Algorithm Hash digest
SHA256 92c42962ae5188bd6cf3881cedaaf10daca34c5f3bf4c978f312181f4c3d6eea
MD5 826920a14ee7b631e90997949252d837
BLAKE2b-256 a36fb3551377dbf98a809ca0731f8c3fb04910cff94f300a47c8859536719924

See more details on using hashes here.

Provenance

The following attestation bundles were made for threatzone-1.0.0.tar.gz:

Publisher: publish.yml on Malwation/threatzone-python-sdk

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

File details

Details for the file threatzone-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: threatzone-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 62.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for threatzone-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9605caa075dfd20ca29645a5fa26771bef2ba1e864e4eaa462c4fbecd7f82404
MD5 5c6ff2d536c67455489907d9e34b2779
BLAKE2b-256 06a1636892f0f65130f325beafa98d7e58f13231b55dbde74bb31a37e19e1bee

See more details on using hashes here.

Provenance

The following attestation bundles were made for threatzone-1.0.0-py3-none-any.whl:

Publisher: publish.yml on Malwation/threatzone-python-sdk

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