Skip to main content

Getting started

Create a new repository from the Rust plugin template by clicking Use this template on GitHub. Clone your new repository and rename the project in Cargo.toml and plugin.toml to match your plugin name.The template gives you a working plugin with Cargo configuration, a plugin.toml manifest, a build.rs, example source code, and CI already set up.

Prerequisites

  • Rust toolchain (stable, 2024 edition)

Project structure

Cargo.toml

plugin.toml

Every plugin needs a plugin.toml manifest alongside its binary. This tells the daemon how to manage your plugin.
See the Plugin Configuration Reference for the full field list, defaults, and validation rules.

build.rs

The build.rs ensures cargo re-runs the proc-macro when plugin.toml changes:

src/main.rs

The SDK uses attribute macros to wire your plugin into the runtime. You annotate your struct and impl block instead of manually implementing traits.
The #[malbox::handlers] macro scans your impl block for annotated methods and generates the necessary trait implementations. Your method names can be anything you like - the attributes determine their role.

Handler methods

When on_start takes a typed parameter, the macro deserializes the raw HashMap<String, String> config into that type automatically.

Pushing results

Results are pushed to the daemon via ctx.results(). You can call push methods multiple times to stream results incrementally. There are three result types:
json() returns Result<PluginResult> (serialization can fail), while bytes() and file() return PluginResult directly.Each result name should match an entry in your plugin.toml under [results.*].

Reports

For structured analysis output with verdicts, indicators, TTPs, and frontend-renderable sections, use the ReportBuilder to construct a Report and push it as a result. Reports support:
  • Verdicts with classification (clean/suspicious/malicious/unknown), confidence, and score
  • Indicators (IOCs) with open-vocabulary types like sha256, ipv4, domain
  • TTPs referencing MITRE ATT&CK techniques
  • Artifact references linking to sibling PluginResult entries
  • Presentation sections with typed blocks (markdown, tables, code, hex dumps, graphs, timelines, and more)
See the results and reports reference for the complete type catalog, or the SDK reference for builder API methods.

Handling errors

The SDK uses its own Result<T> type aliased to std::result::Result<T, SdkError>. Handler methods return Result<()> and can use ? to propagate errors naturally.

Subscribing to events

Declare subscriptions in the [events] section of your plugin.toml, then use #[malbox::on_event(...)] in your handler impl to react to specific event variants:
Event handlers are called with no arguments (the event metadata is matched internally by the macro). Handlers can optionally return Result<()>.See the Events Reference for the full list of available events.

Holding state

Your plugin struct can hold fields. For concurrent access with ExecutionContext::Parallel, wrap mutable state in Mutex or similar:

Thread safety

When using ExecutionContext::Parallel, multiple on_task calls may execute concurrently. Protect shared mutable state with Mutex, RwLock, or atomic types. Health checks may also arrive on a different thread regardless of execution context.

Testing

The SDK provides a testkit feature for writing unit tests without a running daemon. Enable it in your Cargo.toml:
This gives you Context::test_new() to create a mock context for testing handler logic.

Build

Linux

Host plugins always target Linux (they run on the daemon machine). Guest plugins targeting a Linux guest VM also use this.

Deploy

Place the compiled binary and plugin.toml in a subdirectory of the daemon’s plugin directory. The daemon discovers plugins automatically on startup.
~/.config/malbox/plugins/
my-host-plugin-bin
plugin.toml

Examples

See the example plugins on GitHub.