This page documents the complete plugin.toml manifest schema. For conceptual information, see Plugin Configuration.
Full example
[plugin]
name = "my-plugin"
version = "0.1.0"
description = "My analysis plugin"
authors = ["Your Name"]
type = "guest" # or "host"
binary = "my-plugin.exe" # optional, defaults to directory name
[runtime]
state = "ephemeral" # or "persistent", "scoped"
execution = "exclusive" # or "sequential", "parallel", "unrestricted"
port = 50051 # gRPC listen port (default: 50051)
log_filter = "info" # tracing filter (default: "info")
analysis_timeout = 300 # max analysis time in seconds (default: 300)
[runtime.paths]
sample_dir = "C:\\malbox\\samples"
artifact_dir = "C:\\malbox\\artifacts"
stash_dir = "C:\\malbox\\stash"
log_dir = "C:\\malbox\\logs"
external_log_dir = "C:\\malbox\\ext-logs"
[runtime.stash]
threshold_bytes = 1048576
ttl_secs = 120
[runtime.auto_collect.artifacts]
enabled = true
include = ["**/*"]
exclude = []
max_file_size = 52428800
[runtime.auto_collect.external_logs]
enabled = true
include = ["**/*"]
exclude = []
max_file_size = 52428800
[events]
subscribe = ["string-extractor", "network-analyzer"]
[events.filters.PluginResultAvailable]
from_plugins = ["string-extractor"]
[scope]
plugins = ["related-plugin"]
task_types = ["full-analysis"]
[results.my_result]
description = "What this result contains"
user_visible = true
display_name = "My Result"
render = "json"
[plugin]
Core plugin identity. This section is required.
| Field | Type | Required | Description |
|---|
name | string | Yes | Unique plugin name. Must be alphanumeric, -, or _ only. |
version | string | Yes | Semantic version (e.g. "0.1.0"). Must be valid semver. |
description | string | No | Human-readable description. |
authors | string[] | No | List of author names. |
type | string | Yes | Plugin type: "host" or "guest". |
binary | string | No | Executable filename. Defaults to the plugin directory name. Relevant for Python plugins ("main.py"). |
[runtime]
Controls how the plugin runtime behaves. For guest plugins, the build process bakes these values into the plugin binary. For host plugins, the daemon reads them at registry scan time.
| Field | Type | Required | Default | Description |
|---|
state | string | Yes | - | Plugin state management mode ("ephemeral", "persistent", or "scoped"). |
execution | string | Yes | - | Execution context ("exclusive", "sequential", "parallel", or "unrestricted"). |
port | u16 | No | 50051 | gRPC listen port. Must be >= 1024. Guest plugins only. |
log_filter | string | No | "info" | Tracing directive string (same syntax as tracing_subscriber::EnvFilter). Examples: "info", "debug", "info,hyper=warn". |
analysis_timeout | integer | No | 300 | Maximum analysis time in seconds. Must be >= 1. The daemon wraps this with an additional grace period for result flushing. |
Plugin types
| Type | Description |
|---|
"guest" | Executes inside a sandboxed VM. Communicates via gRPC. Terminated with the sandbox after task completion. |
"host" | Executes directly on the host system via iceoryx2 IPC. Can persist across multiple tasks. |
Execution contexts
| Value | Description |
|---|
"exclusive" | Only one instance runs at a time across the entire daemon. |
"sequential" | Tasks are dispatched one at a time, in order. |
"parallel" | Multiple tasks may run concurrently. |
"unrestricted" | No constraints on concurrency or ordering. |
State management
| Value | Description |
|---|
"persistent" | Stays running between tasks. Host plugins only. |
"ephemeral" | Spun up per task and torn down immediately after. |
"scoped" | Lives for the duration of an analysis scope (e.g. a batch). Requires a [scope] section. |
"scoped" state is not yet implemented. Plugins configured with state = "scoped" will fail to start.
[runtime.paths]
All paths must be absolute. Guest plugins may use Windows-style absolute paths (e.g. C:\malbox\samples).
| Field | Type | Default (unix) | Default (windows) | Description |
|---|
sample_dir | string | /tmp/malbox/samples | C:\malbox\samples | Where the daemon pushes the sample for analysis. |
artifact_dir | string | /tmp/malbox/artifacts | C:\malbox\artifacts | Where the plugin writes output artifacts. Auto-collected after task execution. |
stash_dir | string | /tmp/malbox/stash | C:\malbox\stash | Internal result stash spillover directory. |
log_dir | string | /tmp/malbox/logs | C:\malbox\logs | SDK-internal log overflow files directory. |
external_log_dir | string | /tmp/malbox/ext-logs | C:\malbox\ext-logs | External log files from kernel drivers or other tools. Auto-collected after task execution. |
[runtime.stash]
| Field | Type | Default | Description |
|---|
threshold_bytes | integer | 1048576 (1 MiB) | Result payloads larger than this are spilled to disk via the result stash. Must be >= 4096. |
ttl_secs | integer | 120 | How long stashed result entries are kept before TTL sweep reclaims them. Must be >= 1. |
[runtime.auto_collect]
Controls automatic file collection from artifact_dir and external_log_dir after each task completes. The runtime streams files in these directories back to the daemon as results, so your plugin does not need to send them explicitly.
For artifacts, the runtime skips files you already sent explicitly (via ctx.results().push(PluginResult::file(...))) or marked with ctx.mark_collected() to avoid duplicates. External logs are always collected without deduplication.
[runtime.auto_collect.artifacts]
| Field | Type | Default | Description |
|---|
enabled | bool | true | Whether to auto-collect files from artifact_dir. |
include | string[] | ["**/*"] | Glob patterns for files to include. |
exclude | string[] | [] | Glob patterns for files to exclude. |
max_file_size | integer | 52428800 (50 MiB) | Files larger than this are skipped. |
[runtime.auto_collect.external_logs]
| Field | Type | Default | Description |
|---|
enabled | bool | true | Whether to auto-collect files from external_log_dir. |
include | string[] | ["**/*"] | Glob patterns for files to include. |
exclude | string[] | [] | Glob patterns for files to exclude. |
max_file_size | integer | 52428800 (50 MiB) | Files larger than this are skipped. |
[events]
Configures event subscriptions for host plugins. Guest plugins do not support event hooks.
| Field | Type | Required | Description |
|---|
subscribe | string[] | No | List of plugin names to subscribe to. Your plugin will receive events from these plugins’ event channels. |
[events.filters.<EventName>]
Per-event-type filters. <EventName> is the event variant name (e.g. PluginResultAvailable).
| Field | Type | Required | Description |
|---|
from_plugins | string[] | No | Only deliver this event type when it originates from one of these plugins. |
[scope]
Required when state = "scoped". Defines the scope boundary for the plugin’s lifetime.
| Field | Type | Required | Description |
|---|
plugins | string[] | No | Plugins that share this scope. |
task_types | string[] | No | Task types that share this scope. |
[results.<name>]
Declares result entries that this plugin may produce. Each key under [results] is a result name that matches what you pass to PluginResult::json("name", ...), PluginResult::bytes("name", ...), or PluginResult::file("name", ...).
| Field | Type | Required | Description |
|---|
description | string | No | What this result contains. |
user_visible | bool | No | Whether this result should be shown in the frontend UI. |
display_name | string | No | Human-readable name for display in the UI. |
render | string | No | Rendering hint for the frontend (e.g. "json"). |
Validation
The daemon validates the manifest when scanning plugin directories. It marks plugins with invalid manifests as Invalid in the registry and does not start them. The daemon enforces the following constraints:
| Constraint | Rule |
|---|
| Plugin name | Must be non-empty. Only alphanumeric characters, -, and _ allowed. |
| Version | Must be valid semver. |
| Port | Must be >= 1024. |
| All paths | Must be absolute (unix-style or Windows-style for guest plugins). |
threshold_bytes | Must be >= 4096. |
ttl_secs | Must be >= 1. |
analysis_timeout | Must be >= 1. |
log_filter | Must be a valid tracing_subscriber::EnvFilter directive. |
| Scoped state | Requires a [scope] section. |
Changing any runtime setting requires rebuilding the plugin (for guest plugins) or restarting the daemon (for host plugins).