Metadata-Version: 2.5
Name: malwagon
Version: 0.1.2
Summary: Submit a file to the Malwagon malware analysis sandbox and print the verdict.
Project-URL: Homepage, https://malwagon.com
Project-URL: Documentation, https://malwagon.com/docs/api
Project-URL: Source, https://github.com/Malwagon/malwagon-cli
Project-URL: Issues, https://github.com/Malwagon/malwagon-cli/issues
Project-URL: Changelog, https://github.com/Malwagon/malwagon-cli/releases
Author-email: Malwagon <info@malwagon.com>
License-Expression: MIT
License-File: LICENSE
Keywords: cli,dfir,malware,malware-analysis,sandbox,security,threat-intelligence
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Description-Content-Type: text/markdown

<div align="center">

<img src="docs/img/logo.svg" alt="Malwagon logo" width="88" height="88">

# malwagon

### Scan a file for malware from your terminal, and get a scored verdict back

**Automated malware analysis sandbox in one command.** Upload a file and it detonates in an isolated
virtual machine, observed **agentless at the hypervisor layer**, so there is no in-guest agent for a sample
to find, unhook or disable. Windows kernel drivers get a dedicated **BYOVD analysis** module, and an
**AI layer** explains the run in words. You get back a scored verdict, the indicators behind it, and an exit
code your pipeline can gate on.

[![PyPI](https://img.shields.io/pypi/v/malwagon?logo=pypi&logoColor=white&label=PyPI)](https://pypi.org/project/malwagon/)
[![Python](https://img.shields.io/pypi/pyversions/malwagon?logo=python&logoColor=white)](https://pypi.org/project/malwagon/)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Dependencies](https://img.shields.io/badge/dependencies-none-success)](pyproject.toml)
[![Platforms](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey)](https://pypi.org/project/malwagon/)

[Install](#-install) &middot;
[Quick start](#-quick-start) &middot;
[Why it is different](#-why-this-sandbox-is-different) &middot;
[Screenshots](#-screenshots) &middot;
[CI/CD](#-use-it-in-cicd) &middot;
[FAQ](#-faq)

</div>

---

<div align="center">
  <img src="docs/img/cli-terminal.png" alt="malwagon CLI scanning a suspicious executable and printing a malicious verdict with a score of 100 out of 100 and a link to the full sandbox report" width="820">
</div>

---

## &#128230; Install

```bash
pip install malwagon
```

That is the whole dependency list: **none.** The standard library makes the HTTPS request, so installing a
malware analysis client does not widen your supply chain by four packages.

Works on **Linux, macOS and Windows**, Python **3.8+**.

## &#9889; Quick start

```bash
# 1. get a free API key at https://malwagon.com  (Settings -> API tokens)
export MALWAGON_API_KEY=mwg_...

# 2. scan anything
malwagon suspicious.exe
malwagon driver.sys
malwagon payload.elf
malwagon dropper.ps1
malwagon invoice.docm
```

```console
$ malwagon suspicious.exe
uploading suspicious.exe (412.0 KB) to malwagon.com
scan 48213 queued
waiting for the sandbox, usually 90 to 300 seconds
  queued       0s elapsed
  running      12s elapsed
  analyzing    2m 18s elapsed

  MALICIOUS  score 88/100
  sha256 354fd5f5e4afc2280a19c8541fd4abe38bf8fb73efbeb3c2b0a4f2b1d9e0c7a1
  report https://malwagon.com/s/48213
```

**The sandbox is chosen from the file.** A Windows binary detonates on Windows, an ELF or a pip package on
the Linux sandbox, a kernel driver reaches the BYOVD analyzer. There is no flag to get wrong.

## &#128187; Three ways to run it

| | |
|---|---|
| **Installed command** | `malwagon suspicious.exe` |
| **Python module** | `python -m malwagon suspicious.exe` |
| **From a clone, no install** | `git clone https://github.com/Malwagon/malwagon-cli && cd malwagon-cli`<br>`PYTHONPATH=src python -m malwagon suspicious.exe` |

### As a Python library

The client is importable, so a script can submit and poll without shelling out:

```python
import os, time
from malwagon.client import Client

client = Client("https://malwagon.com", os.environ["MALWAGON_API_KEY"])

with open("suspicious.exe", "rb") as handle:
    status, body, _ = client.submit_file(handle, "suspicious.exe", {"private": "true"})

scan_id = body["scan"]["scan_id"]
print("report:", client.report_url(scan_id))

while True:
    status, body, _ = client.scan_status(scan_id)
    scan = body["scan"]
    if scan["terminal"]:
        break
    time.sleep(10)

print(scan["verdict"], scan["score"])     # -> malicious 88
```

Every response is bounded before it is parsed, TLS is verified, and redirects are never followed. See
[What this client will not do](#-what-this-client-will-not-do).

---

## &#128302; Why this sandbox is different

### &#129517; Hypervisor-level, agentless observation

**Behaviour is recorded from outside the guest.** The analysis is logged at the hypervisor layer rather than
by a driver or a hooking DLL installed inside the virtual machine, so there is no in-guest agent for a sample
to find, unhook or disable. Malware that checks for analysis tooling in its own process space finds an
ordinary Windows desktop.

Real virtual machines on real hardware the operator runs. Not an emulator, not a container.

### &#128737; BYOVD and kernel driver analysis

**A dedicated module for Windows kernel-mode PE images.** Bring Your Own Vulnerable Driver is how modern
ransomware turns off endpoint protection, and a driver is not an ordinary executable: the questions are which
primitive it hands to user mode, which control codes reach it, and whether the world already knows it is
abusable.

The kernel module returns the **IOCTL dispatch surface**, the **privileged hardware access in the code**
(physical memory mapping, MSR access, arbitrary process termination), the **signing and mitigation state**,
an **ATT&CK mapping in kill-chain order**, and **generated Sigma rules** as a downloadable bundle.

Every import, rule and hardware primitive is weighed against how common it is across a corpus of real signed
drivers, so an ordinary call is not reported as a finding.

### &#129504; AI analysis on derived data only

**The narrative layer explains the run in words, and never sees the sample.** It receives a behaviour summary,
the API call sequence, the indicator list and non-sensitive extracted strings, assembled locally by one module
that copies named fields and drops everything else.

The raw sample is never sent to any model, and never leaves the analysis host. The AI layer reads what the
platform already worked out; it does not do the working out.

### &#128200; Four layers, one score

| Layer | What it contributes |
|---|---|
| **Static** | PE structure, packing and signing, capability detection, YARA, extracted strings |
| **Dynamic** | Process tree, file and registry activity, network, persistence, memory, screen recording |
| **Threat intelligence** | Reputation on hashes and derived indicators, open indicator feeds |
| **AI** | A written explanation of what the run did, from derived data only |

Each layer's contribution to the score is shown, so a verdict is auditable rather than an oracle.

---

## &#128444; Screenshots

### The platform this client talks to

Drop a file in the browser, or send it from your shell with the same account. Seven submission
modules: file, hash, command, URL, document, package and Windows kernel driver.

<div align="center">
  <img src="docs/img/landing.png" alt="Malwagon malware analysis sandbox home page showing the file, hash, command, URL, document, package and kernel driver submission tabs above a drag and drop upload area" width="900">
</div>

### The report a scan produces

Score, the reasoning behind it, which layers ran and what each one moved.

<div align="center">
  <img src="docs/img/report-verdict.png" alt="Malwagon scan report showing a malicious verdict scoring 100 out of 100, the runtime behaviour, persistence, threat intelligence and static analysis contributions to the score, and which analysis layers ran" width="900">
</div>

---

## &#9881; Options

```console
malwagon FILE [options]
```

| Option | Effect |
|---|---|
| `--json` | Print one JSON object and nothing else |
| `--no-wait` | Submit and exit immediately with the scan id |
| `--private` | Keep the report private (needs a plan that includes it) |
| `--internet` | Detonate with internet access (paid plans) |
| `--os KEY` | Force a sandbox image instead of letting the file decide |
| `--timeout-run N` | How long the sample runs inside the sandbox |
| `--no-dynamic` | Static analysis only, no detonation |
| `--quiet` | Drop the progress lines, keep the result |
| `--api-key-file PATH` | Read the key from a file |
| `--api-key-stdin` | Read the key from stdin |
| `--ca-bundle PATH` | Verify TLS against your own CA bundle |

`malwagon --help` lists every option.

### Machine-readable output

```console
$ malwagon sample.dll --json
{
  "limitations": [],
  "report_url": "https://malwagon.com/s/48213",
  "scan_id": 48213,
  "score": 88,
  "sha256": "354fd5f5e4afc2280a19c8541fd4abe38bf8fb73efbeb3c2b0a4f2b1d9e0c7a1",
  "size": 421888,
  "status": "completed",
  "verdict": "malicious",
  "verdict_raw": null
}
```

Progress goes to **stderr** and the result to **stdout**, so `malwagon sample.bin --json | jq` works while you
still watch the wait.

---

## &#128736; Use it in CI/CD

The exit code **is** the verdict, so a build step can gate on it with no parsing:

| Code | Meaning |
|---|---|
| `0` | Clean |
| `1` | Malicious |
| `2` | Error |
| `3` | Suspicious |

```bash
malwagon dist/installer.exe --quiet || { echo "do not ship this"; exit 1; }
```

**GitHub Actions**

```yaml
- name: Detonate the release artifact
  env:
    MALWAGON_API_KEY: ${{ secrets.MALWAGON_API_KEY }}
  run: |
    pip install malwagon
    malwagon dist/installer.exe --json --quiet | tee scan.json
```

**GitLab CI**

```yaml
malware-scan:
  script:
    - pip install malwagon
    - malwagon dist/installer.exe --quiet
```

Useful for scanning build artifacts before release, third-party binaries before they reach a fleet, and
attachments pulled out of a phishing report.

---

## &#128274; Authentication

The key comes from one of these, highest first:

1. `--api-key-file PATH`
2. `--api-key-stdin`
3. `MALWAGON_API_KEY` in the environment
4. the config file written by `malwagon login`
5. an interactive prompt when stdin is a terminal

```console
$ malwagon login
Malwagon API key for malwagon.com:
key accepted and saved to ~/.config/malwagon/config.json
```

The file is created mode `0600`, and the client refuses to read it if the rest of the machine can.

> **There is deliberately no `--api-key` flag.** A credential on the command line is visible to every process
> on the machine through the process list, and is written verbatim into your shell history and into CI job
> logs. The absence is a feature, and there is a test that keeps it absent.

---

## &#128737; What this client will not do

Everything here is enforced in code, and each one has a test:

- **It will not disable TLS verification.** There is no `--insecure`, and there will not be one. `--ca-bundle`
  exists for a private deployment.
- **It will not follow redirects.** A redirect is the standard way a bearer token is walked onto a host it was
  not issued for. The client reports the `Location` instead of chasing it.
- **It will not send your key to a host it was not stored for.** Keys are bound per host, so
  `--api-url https://evil.example` cannot harvest a credential stored for somewhere else.
- **It will not send plain HTTP anywhere but loopback.**
- **It will not upload what you did not mean to upload.** Symlinks, devices, pipes, directories, empty files
  and anything shaped like a private key or a credential file are refused unless you insist. Every check is
  made on the open file descriptor rather than on the path, so there is no window between the check and the
  read.
- **It will not trust the server's text on your terminal.** ANSI escapes, carriage returns, OSC 8 hyperlinks,
  clipboard writes and bidirectional overrides are stripped before anything is printed, and the verdict is
  read from a fixed vocabulary rather than echoed as the server spelled it.
- **It will not parse an unbounded response.** Bodies are capped before decoding, and the cap applies to the
  decompressed stream.

---

## &#128176; Plans

A **free Community key works** and runs a **network isolated** scan: no internet egress from the sandbox, and
no threat intelligence or AI layer on the report.

The client says which layers did not run, rather than leaving an empty section to be read as "the sample did
nothing":

```console
  CLEAN  score 10/100
  report https://malwagon.com/s/48213

  - threat intelligence lookups did not run
  - the AI narrative did not run
    a paid plan adds internet egress, threat intelligence and the
    AI narrative to this report
```

| | Community | Paid |
|---|---|---|
| File, driver, document and script analysis | Yes | Yes |
| Hypervisor-level dynamic analysis | Yes | Yes |
| Live VNC while the sample runs | Yes | Yes |
| Internet egress from the sandbox | No | Yes |
| Threat intelligence enrichment | No | Yes |
| AI narrative | No | Yes |
| Private reports | No | Yes |

---

## &#10067; FAQ

### What is a malware analysis sandbox?

A malware analysis sandbox runs a suspicious file inside an isolated virtual machine and records what it
actually does: the processes it starts, the files and registry keys it touches, the network it reaches and the
persistence it installs. It answers "what does this do" rather than "does a signature match".

### How do I scan a file for malware from the command line?

Install the client with `pip install malwagon`, set `MALWAGON_API_KEY`, then run `malwagon suspicious.exe`.
The command uploads the file, waits for the detonation, prints a scored verdict and a link to the full report,
and exits `1` if the verdict is malicious.

### Is it free?

Yes, on the Community plan. Scans run network isolated and without the threat intelligence and AI layers. Paid
plans add internet egress, reputation enrichment, the AI narrative and private reports.

### Does the sample leave my machine?

Yes, it is uploaded to the analysis platform, because it has to be detonated there. Use `--private` on a plan
that includes private reports if the analysis should not be published to the public corpus.

### What is agentless sandbox analysis?

Agentless means behaviour is recorded from outside the guest, at the hypervisor layer, rather than by software
installed inside the virtual machine. There is no in-guest agent for a sample to detect, unhook or disable.

### What is BYOVD?

Bring Your Own Vulnerable Driver: an attacker loads a legitimately signed but exploitable kernel driver to get
kernel-level access, typically to disable endpoint protection. The kernel driver module analyses the driver's
IOCTL dispatch surface and privileged hardware access to answer whether it hands that primitive out.

### Can I use it in a CI pipeline?

Yes. The exit code is the verdict (`0` clean, `1` malicious, `3` suspicious), so a build step gates on it with
no parsing. `--json` gives a machine-readable object on stdout while progress stays on stderr.

### Does it work on Windows?

Yes. Linux, macOS and Windows, Python 3.8 and newer. The client uses no POSIX-only calls without a guard, and
the config file lives under `%APPDATA%` on Windows.

### What file types can it analyse?

Windows executables and DLLs, Windows kernel drivers (`.sys`), Linux ELF binaries, Office documents and PDFs,
scripts (PowerShell, batch, VBS, JS, Python), archives, and pip packages. The platform types the sample by its
content, not by its extension.

---

## &#128279; Links

| | |
|---|---|
| **Platform** | <https://malwagon.com> |
| **API reference** | <https://malwagon.com/docs/api> |
| **Command line docs** | <https://malwagon.com/docs/api#cli> |
| **Public scan corpus** | <https://malwagon.com/samples> |
| **PyPI package** | <https://pypi.org/project/malwagon/> |

## &#128220; License

MIT. See [LICENSE](LICENSE).

---

<p align="center">
<sub><b>Keywords</b> &middot; malware analysis sandbox &middot; automated malware analysis &middot; dynamic analysis &middot; static analysis &middot; hypervisor-level monitoring &middot; agentless sandbox &middot; BYOVD &middot; vulnerable driver analysis &middot; kernel driver analysis &middot; AI malware analysis &middot; threat intelligence &middot; IOC extraction &middot; YARA &middot; Sigma rules &middot; MITRE ATT&amp;CK &middot; DFIR &middot; malware sandbox CLI &middot; malware scanning API &middot; CI/CD malware scanning</sub>
</p>
