Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.malbox.app/llms.txt

Use this file to discover all available pages before exploring further.

Complete API reference for the Malbox C++20 Plugin SDK. For a step-by-step walkthrough, see the Creating a C++ Plugin guide.

Plugin Base Class

Every plugin subclasses malbox::Plugin and implements on_task at minimum. All other methods have default no-op implementations.
#include <malbox/plugin.hpp>

class MyPlugin final : public malbox::Plugin {
    void on_task(const Task& task, const Context& ctx) override;
};

Lifecycle Methods

on_task (required)

Called for each assigned analysis task. This is where your analysis logic lives. Push results to the daemon via ctx.push_result().
virtual void on_task(const Task& task, const Context& ctx) = 0;
task
const Task&
required
Handle to the current task. Provides access to the sample and task configuration. Non-owning, do not store.
ctx
const Context&
required
Runtime communication handle for pushing results, emitting progress, warnings, and events. Non-owning, do not store.

on_start

Called once before any tasks arrive. Use for initialization.
virtual void on_start(const std::unordered_map<std::string, std::string>& config);
config
const std::unordered_map<std::string, std::string>&
Key-value configuration map from the daemon and plugin.toml settings.

on_stop

Called once on shutdown. Clean up resources here.
virtual void on_stop();

health_check

Called periodically by the runtime to check plugin health.
virtual HealthStatus health_check();
return
HealthStatus
A struct with ready (bool) and reason (string) fields.

Event Handlers

Override these to react to system events. All are optional and default to no-ops. See the Events Reference for the full list of events in each category.

on_daemon_event

Triggered by system-wide events such as shutdown or configuration reload.
virtual void on_daemon_event(DaemonEvent event, const Context& ctx);
event
DaemonEvent
required
The daemon event that occurred (DaemonShutdown or ConfigReloaded).
ctx
const Context&
required
Runtime communication handle.

on_task_event

Triggered by task lifecycle events (created, starting, completed, failed).
virtual void on_task_event(TaskEvent event, const TaskEventPayload& payload, const Context& ctx);
event
TaskEvent
required
The task event that occurred.
payload
const TaskEventPayload&
required
Contains the task_id of the affected task.
ctx
const Context&
required
Runtime communication handle.

on_plugin_event

Triggered by plugin process events (started, stopped, result produced).
virtual void on_plugin_event(PluginEvent event, const PluginEventPayload& payload, const Context& ctx);
event
PluginEvent
required
The plugin event that occurred.
payload
const PluginEventPayload&
required
Contains the plugin_id of the affected plugin.
ctx
const Context&
required
Runtime communication handle.

on_sample_event

Triggered by sample processing events (started, stopped, result produced).
virtual void on_sample_event(SampleEvent event, const SampleEventPayload& payload, const Context& ctx);
event
SampleEvent
required
The sample event that occurred.
payload
const SampleEventPayload&
required
Contains the sample_id of the affected sample.
ctx
const Context&
required
Runtime communication handle.

Task

Provides access to the current analysis task. Task is a non-owning handle, valid only during the on_task callback. Do not store it.

id()

int32_t id();
return
int32_t
Unique identifier for this task.

sample_path()

std::string sample_path();
return
std::string
Absolute path to the sample on disk.

sample_bytes()

Reads the entire sample file into memory. Throws malbox::Error on I/O failure.
std::vector<uint8_t> sample_bytes();
return
std::vector<uint8_t>
The raw bytes of the sample file.

config()

std::unordered_map<std::string, std::string> config();
return
std::unordered_map<std::string, std::string>
All configuration key-value pairs for this task.

config_value()

std::optional<std::string> config_value(const std::string& key);
key
const std::string&
required
The configuration key to look up.
return
std::optional<std::string>
The value if found, or std::nullopt.

Context

Used to communicate with the runtime during task execution. Context is a non-owning handle, valid only during the callback. Do not store it.

push_result()

Pushes a single result to the daemon. Call one or more times during on_task to stream results incrementally.
void push_result(const PluginResult& result) const;
result
const PluginResult&
required
The result to send to the daemon.

emit_progress()

Reports task progress to the runtime.
void emit_progress(double fraction, const std::string& message);
fraction
double
required
Progress value clamped to [0.0, 1.0].
message
const std::string&
required
Human-readable status message (e.g. "scanning signatures").

warn()

Attaches a warning message to the task report.
void warn(const std::string& message);
message
const std::string&
required
The warning message to attach.

mark_collected()

Marks a file as already handled, preventing artifact auto-collection from sending it again. Use this when a plugin reads a file from the artifacts directory, processes it, and sends derived data as Json/Bytes instead of the raw file. Files sent via push_result(PluginResult::file(...)) are automatically marked.
void mark_collected(const std::string& path);
path
const std::string&
required
Absolute path to the file to mark as handled.

emit_event()

Emits a raw system event. This is an advanced escape hatch for custom event routing.
void emit_event(Event event, Payload payload);
event
Event
required
The event to emit.
payload
Payload
required
The event payload.

PluginResult

Pushed via ctx.push_result() during on_task to report analysis findings. Each result name should correspond to a [results.*] entry in your plugin.toml.

PluginResult::json()

Creates a JSON-encoded result from raw UTF-8 bytes.
static PluginResult json(const std::string& name, std::span<const uint8_t> data);
name
const std::string&
required
Result identifier matching a [results.*] key in plugin.toml.
data
std::span<const uint8_t>
required
Raw UTF-8 encoded JSON bytes.

PluginResult::bytes()

Creates a raw binary result.
static PluginResult bytes(const std::string& name, std::span<const uint8_t> data);
name
const std::string&
required
Result identifier matching a [results.*] key in plugin.toml.
data
std::span<const uint8_t>
required
Raw binary data.

PluginResult::file()

Creates a result referencing a file on disk. The runtime reads the file contents.
static PluginResult file(const std::string& name, const std::string& path);
name
const std::string&
required
Result identifier matching a [results.*] key in plugin.toml.
path
const std::string&
required
Absolute filesystem path to the result file.

Report

#include <malbox/report.hpp> A structured result envelope with semantic metadata and a presentation layer for frontend rendering. All report types live in the malbox::report namespace.

Report

struct Report {
    uint32_t schema_version = SCHEMA_VERSION;
    PluginInfo plugin;
    std::optional<Verdict> verdict;
    std::vector<Indicator> indicators;
    std::vector<Ttp> ttps;
    std::vector<ArtifactRef> artifacts;
    std::optional<std::string> summary;
    std::vector<Section> sections;
    std::string raw_json;
};

to_json()

Serializes a report to a JSON string.
std::string to_json(const Report& r);

into_plugin_result()

Serializes a report and wraps it as a PluginResult with the well-known name "report".
PluginResult into_plugin_result(const Report& r);

PluginInfo

struct PluginInfo {
    std::string id;
    std::string version;
    std::optional<std::string> display_name;
};

Semantic Types

Classification

enum class Classification : uint8_t { Clean, Suspicious, Malicious, Unknown };

Confidence

enum class Confidence : uint8_t { Low, Medium, High };

Verdict

struct Verdict {
    Classification classification;
    std::optional<uint8_t> score;       // 0-100
    std::optional<Confidence> confidence;
    std::vector<std::string> labels;    // free-form tags
};

Indicator

IOC with an open-vocabulary kind (e.g. "sha256", "ipv4", "domain", "yara_rule").
struct Indicator {
    std::string kind;
    std::string value;
    std::optional<std::string> context;
    std::optional<std::string> first_seen;  // ISO 8601 timestamp

    Indicator(std::string kind, std::string value);
    Indicator& context(std::string ctx);
    Indicator& first_seen(std::string ts);
};

Ttp

MITRE ATT&CK technique reference.
struct Ttp {
    std::string id;                     // e.g. "T1055" or "T1055.005"
    std::string name;                   // e.g. "Process Injection"
    std::optional<std::string> evidence;

    Ttp(std::string id, std::string name);
    Ttp& evidence(std::string ev);
};

ArtifactRef

Reference to a sibling PluginResult by name.
struct ArtifactRef {
    std::string result_name;
    std::string kind;                   // e.g. "yara", "pcap", "json"
    std::optional<std::string> description;

    ArtifactRef(std::string result_name, std::string kind);
    ArtifactRef& description(std::string desc);
};

Presentation Types

Section

struct Section {
    std::string id;
    std::string title;
    std::vector<Block> blocks;
};

Block

A std::variant of all supported block types:
using Block = std::variant<
    BlockMarkdown, BlockCallout, BlockHeading, BlockDivider,
    BlockKv, BlockTable, BlockCode, BlockJson, BlockHex,
    BlockImage, BlockDownload, BlockIocs, BlockTtps,
    BlockTree, BlockTimeline, BlockGraph
>;

Block Types

TypeFields
BlockMarkdowntext
BlockCalloutlevel (CalloutLevel), text
BlockHeadinglevel (1-6), text
BlockDivider(none)
BlockKvpairs (std::vector<KvPair>)
BlockTablecolumns (std::vector<Column>), rows_json (std::vector<std::string>), sortable, searchable
BlockCodelanguage, text
BlockJsondata_json (pre-encoded), collapsed
BlockHexbytes_b64, offset
BlockImageartifact (result name), caption
BlockDownloadartifact (result name), label
BlockIocsitems (std::vector<Indicator>)
BlockTtpsitems (std::vector<Ttp>)
BlockTreenodes (std::vector<TreeNode>)
BlockTimelineevents (std::vector<TimelineEvent>)
BlockGraphnodes (std::vector<GraphNode>), edges (std::vector<GraphEdge>)

CalloutLevel

enum class CalloutLevel : uint8_t { Info, Success, Warn, Error };

Helper Structs

struct KvPair {
    std::string key;
    std::string value;
    bool mono = false;
};

struct Column {
    std::string key;
    std::string label;
    std::string type;   // "string", "number", etc.
};

struct TreeNode {
    std::string label;
    std::string metadata_json;          // pre-encoded JSON
    std::vector<TreeNode> children;
};

struct TimelineEvent {
    std::string timestamp;              // ISO 8601
    std::string label;
    std::optional<std::string> severity;
    std::string metadata_json;
};

struct GraphNode {
    std::string id;
    std::string label;
    std::string metadata_json;
};

struct GraphEdge {
    std::string from;
    std::string to;
    std::optional<std::string> label;
};

ReportBuilder

Fluent API for constructing a Report.
class ReportBuilder {
public:
    ReportBuilder(std::string plugin_id, std::string plugin_version);

    ReportBuilder& display_name(std::string name);
    ReportBuilder& summary(std::string s);
    ReportBuilder& verdict(Classification c,
        std::optional<uint8_t> score = {},
        std::optional<Confidence> conf = {});
    ReportBuilder& labels(std::vector<std::string> ls);
    ReportBuilder& indicator(Indicator i);
    ReportBuilder& ttp(Ttp t);
    ReportBuilder& artifact(ArtifactRef a);
    ReportBuilder& raw(std::string pre_encoded_json);

    ReportBuilder& section(SectionBuilder sb);

    template <typename F>
    ReportBuilder& section(std::string id, std::string title, F&& fn);

    Report build();
};

SectionBuilder

Fluent API for constructing a Section with typed blocks.
class SectionBuilder {
public:
    SectionBuilder(std::string id, std::string title);

    SectionBuilder& block(Block b);
    SectionBuilder& markdown(std::string text);
    SectionBuilder& callout(CalloutLevel level, std::string text);
    SectionBuilder& heading(uint8_t level, std::string text);
    SectionBuilder& divider();
    SectionBuilder& kv(std::vector<KvPair> pairs);
    SectionBuilder& table(std::vector<Column> cols,
        std::vector<std::string> rows_json,
        bool sortable = true, bool searchable = false);
    SectionBuilder& code(std::string language, std::string text);
    SectionBuilder& json(std::string data_json, bool collapsed = true);
    SectionBuilder& hex(std::string bytes_b64, uint64_t offset = 0);
    SectionBuilder& image(std::string artifact, std::optional<std::string> caption = {});
    SectionBuilder& download(std::string artifact, std::string label);
    SectionBuilder& iocs(std::vector<Indicator> items);
    SectionBuilder& ttps(std::vector<Ttp> items);
    SectionBuilder& tree(std::vector<TreeNode> nodes);
    SectionBuilder& timeline(std::vector<TimelineEvent> events);
    SectionBuilder& graph(std::vector<GraphNode> nodes, std::vector<GraphEdge> edges);

    Section build();
};

Constants

constexpr uint32_t SCHEMA_VERSION = 1;
constexpr const char* REPORT_RESULT_NAME = "report";

PluginMeta

Metadata passed to the runtime at startup. All string fields must be null-terminated string literals with static lifetime.
name
const char*
required
Plugin identifier. Must be alphanumeric with - and _ only.
version
const char*
required
Semver version string (e.g. "0.1.0").
description
const char*
Human-readable description. Nullable.
authors
const char*
required
Author name(s).
plugin_type
PluginType
required
PluginType::Host or PluginType::Guest.
state
PluginState
required
PluginState::Persistent, PluginState::Ephemeral, or PluginState::Scoped.
execution
ExecutionContext
required
ExecutionContext::Exclusive, Sequential, Parallel, or Unrestricted.

Enums

ValueDescription
PluginType::GuestRuns inside a VM/container, communicates via gRPC
PluginType::HostRuns on the daemon machine, communicates via IPC

RuntimeConfig

Runtime configuration baked into the plugin binary at build time. Generated from plugin.toml by malbox-codegen (invoked via CMake’s malbox_generate_runtime_config).
#include "malbox_runtime_config.hpp"   // generated header

// Access via: malbox::generated::runtime_config
port
std::uint16_t
required
gRPC listen port.
sample_dir
const char*
required
Absolute path to the directory where the daemon pushes the sample for analysis.
artifact_dir
const char*
required
Absolute path to the directory where the plugin writes output artifacts.
stash_dir
const char*
required
Absolute path to the internal result stash spillover directory.
log_dir
const char*
required
Absolute path to the SDK-internal log overflow files directory.
external_log_dir
const char*
required
Absolute path to external log files directory (kernel drivers, custom tools). Auto-collected after task execution.
stash_threshold_bytes
std::size_t
required
Result stash spill threshold in bytes.
stash_ttl_secs
std::uint64_t
required
Result stash entry TTL in seconds.
log_filter
const char*
required
Tracing EnvFilter directive string (e.g. "info", "info,hyper=warn").
auto_collect_artifacts
AutoCollectConfig
required
Auto-collection settings for artifact files. Contains enabled, include/exclude glob patterns, and max_file_size.
auto_collect_external_logs
AutoCollectConfig
required
Auto-collection settings for external log files. Contains enabled, include/exclude glob patterns, and max_file_size.

Runtime Entry Points

#include "malbox_runtime_config.hpp"

malbox::run_guest_plugin(
    std::make_unique<MyPlugin>(),
    meta,
    malbox::generated::runtime_config);
Both functions block until the runtime shuts down. They throw malbox::Error on failure.
plugin
std::unique_ptr<Plugin>
required
Owning pointer to your plugin instance.
meta
PluginMeta
required
Plugin metadata describing name, version, type, state, and execution context.
config
const RuntimeConfig&
required
Compile-time runtime configuration generated from plugin.toml. Required for guest plugins only.

Error Handling

Plugin methods can throw malbox::Error to signal failures. The SDK catches exceptions at the FFI boundary and reports them to the runtime.
#include <malbox/error.hpp>

throw malbox::Error(-1, "analysis failed: corrupt sample");
code
int32_t
required
Numeric error code. Use -1 for generic failures.
message
const char*
required
Human-readable error description.
SDK methods (like task.sample_bytes()) also throw malbox::Error on failure.

Thread Safety

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

Headers

HeaderContents
malbox/plugin.hppUmbrella header (include this one)
malbox/error.hppmalbox::Error exception class
malbox/types.hppEnums, PluginMeta, HealthStatus
malbox/events.hppEvent types and payloads
malbox/task.hppmalbox::Task wrapper
malbox/context.hppmalbox::Context wrapper
malbox/result.hppmalbox::PluginResult
malbox/report.hppmalbox::report::Report, builders, semantic types, and block types
malbox/handlers.hppmalbox::Plugin base class
malbox/runtime.hppEntry points, RuntimeConfig, and trampolines
malbox_runtime_config.hppGenerated compile-time constexpr RuntimeConfig from plugin.toml