Appearance
The MACATable format is MACAT's native TOML-based format for defining and sharing procedures and simulations. It extends concepts from the Atomic Red Team atomic format with additional fields for file attachments, defense recommendations, threat profiles, and more.
There are two file types:
- .toml — plain text, can optionally embed file content as base64
- .mcz — compressed archive (tar.xz) containing a .toml plus external files
JSON Schemas are available for editor validation and autocomplete:
To use with Taplo (or the Even Better TOML VS Code extension), add this as the first line of your .toml file:
toml
#:schema https://docs.macat.io/schemas/macatable-simulation.schema.jsonDocument Types
A MACATable TOML file is one of two types.
Simulation
A named collection of procedures to execute together:
toml
id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
name = "My Simulation"
version = 1
description = "Optional description"
tags = ["red-team", "apt"]
[[procedures]]
# ...| Field | Type | Required | Description |
|---|---|---|---|
id | UUID string | Yes | Unique identifier |
name | string | Yes | Simulation name |
version | integer | No | Version number (default: 1) |
description | string | No | Description |
tags | string array | No | Tags for categorization |
procedures | array | Yes | Procedures in this simulation |
variables | array | No | Variables shared across the simulation |
icon | table | No | Icon for this simulation. See Icons. |
Library Export
A set of standalone procedures not tied to a simulation:
toml
version = 1
[[lib_procedures]]
# ...| Field | Type | Required | Description |
|---|---|---|---|
version | integer | No | Version number (default: 1) |
lib_procedures | array | Yes | Procedures in this export |
Procedures
Procedure definitions are the same in both document types. They appear as [[procedures]] in simulations and [[lib_procedures]] in library exports.
toml
[[procedures]]
id = "11111111-2222-3333-4444-555555555555"
name = "Scheduled Task Creation"
description = "Creates a scheduled task for persistence"
primary_technique = "T1053.005"
primary_tactic = "persistence"
mitre_tactics_ref = ["persistence", "execution"]
src_type = "macat"
supported_platforms = ["windows"]
threat_profile_ids = ["intrusion-set--abc123"]
possible_defenses = ["edr", "siem"]
tags = ["ransomware", "priority-0"]| Field | Type | Required | Description |
|---|---|---|---|
id | UUID string | Yes | Unique identifier |
ref | string | No | Stable reference for this procedure, used to address its steps from another procedure. snake_case ([a-z][a-z0-9_]*), unique within the simulation. |
name | string | Yes | Procedure name |
description | string | No | Description |
primary_technique | string | No | MITRE ATT&CK technique ID (e.g., T1053.005) |
primary_tactic | string | No | Primary MITRE ATT&CK tactic |
mitre_tactics_ref | string array | No | Related MITRE ATT&CK tactics |
src_type | string | No | "macat" or "art" |
supported_platforms | string array | No | e.g., windows, linux, macos |
threat_profile_ids | string array | No | STIX identity references |
possible_defenses | string array | No | Defense tool types that may detect this |
tags | string array | No | Tags for categorization |
icon | table | No | Icon for this procedure, written as [procedures.icon]. See Icons. |
Procedure Steps
Steps define the commands to execute. Both procedure_steps (main execution) and cleanup_steps (post-execution cleanup) use the same structure.
toml
[[procedures.procedure_steps]]
executor = "powershell"
command = "schtasks /create /tn #{task_name} /tr calc.exe /sc daily"
name = "Create Scheduled Task"
description = "Creates a daily scheduled task"
order = 0
privilege = true
timeout = 300| Field | Type | Required | Description |
|---|---|---|---|
executor | string | Yes | powershell, cmd, bash, sh, or file_extractor |
command | string | No | Command to execute (default: empty). Supports #{variable} substitution. |
ref | string | No | Stable reference for this step, used to address it for artifact wiring. snake_case ([a-z][a-z0-9_]*), unique within the procedure. |
name | string | No | Step name |
description | string | No | Step description |
order | integer | No | Execution order |
privilege | boolean | No | Requires elevated privileges |
timeout | integer | No | Seconds bounding one execution of this step, at least 1. A step's own timeout beats the run's configured default, so a long-running step keeps its time. |
parameters | table | No | Parameters owned by the executor. Values may be any TOML value -- string, number, boolean, array or table. Write it last: a scalar written after this table header belongs to the table, not the step. |
Parameter-Based Executors
Some executors like file_extractor use parameters instead of a command string:
toml
[[procedures.procedure_steps]]
executor = "file_extractor"
order = 1
[procedures.procedure_steps.parameters]
file_ref = "payload"
destination = "C:\\ProgramData"
extract_mode = "auto"Parameter values also support #{variable} substitution.
Cleanup Steps
Same structure, run after execution to undo changes:
toml
[[procedures.cleanup_steps]]
executor = "powershell"
command = "schtasks /delete /tn #{task_name} /f"
order = 0Dependency Checks
Run before procedure steps to verify prerequisites are met:
toml
[[procedures.dependency_checks]]
dependency_check_executor = "powershell"
dependency_check_command = "Get-Command schtasks"
dependency_check_command_privilege = false
dependency_not_found_command = "Write-Host 'schtasks not available'"
name = "Check schtasks"
order = 0| Field | Type | Required | Description |
|---|---|---|---|
dependency_check_executor | string | Yes | Executor type for the check |
dependency_check_command | string | Yes | Command to verify the prerequisite |
dependency_check_command_privilege | boolean | No | Requires elevated privileges |
dependency_not_found_command | string | No | Command to run if the check fails |
timeout | integer | No | Seconds bounding this check, at least 1. Same meaning as a step's timeout. |
name | string | No | Check name |
description | string | No | Check description |
order | integer | No | Execution order |
Icons
An icon is a table, so it is written after the scalar fields of whatever it belongs to -- [icon] for a simulation, [procedures.icon] for a procedure.
toml
[icon]
content_ref = "icons/campaign.svg"
file_name = "campaign.svg"
file_type = "svg"| Field | Type | Required | Description |
|---|---|---|---|
content_ref | string | Yes | Reference to the icon content, resolved against the surrounding package. |
file_name | string | No | Original file name. |
file_type | string | No | File type, e.g. svg or png. |
content | string | No | Inline icon content, for a package carrying the bytes directly. |
Variables
Configurable inputs referenced in commands using #{variable_name} syntax:
toml
[[procedures.variables]]
name = "task_name"
var_type = "string"
default = "MACATTask"
value = "CustomTask"
description = "Name of the scheduled task to create"| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Variable name, referenced as #{name} in commands |
var_type | string | Yes | Type (e.g., string, integer) |
default | string | No | Default value |
value | string | No | Current value, overrides default when set |
description | string | No | Description shown in the UI |
File References
Files can be attached to procedures and referenced by name. The key in the [procedures.files] table is the reference name used in step parameters (e.g., file_ref = "payload").
Database Reference
For files uploaded to MACAT's file storage:
toml
[procedures.files.payload]
location = "db"
name = "agent.exe"
folder = "/uploads"
required = true
sha256 = "e3b0c44..."Embedded
Base64-encoded file content stored inline in the TOML:
toml
[procedures.files.payload]
location = "embedded"
name = "agent.exe"
content = "TVqQAAMAAAA..."
size = 2048
sha256 = "e3b0c44..."
required = trueArchive
File stored inside an MCZ archive:
toml
[procedures.files.payload]
location = "archive"
name = "agent.exe"
path_in_archive = "files/agent.exe"
sha256 = "e3b0c44..."
required = true| Field | Type | Required | Description |
|---|---|---|---|
location | string | Yes | "db", "embedded", or "archive" |
name | string | Yes | Filename |
folder | string | No | Folder path (db) |
content | string | No | Base64-encoded content (embedded) |
path_in_archive | string | No | Path within MCZ (archive) |
size | integer | No | Original file size in bytes |
sha256 | string | No | SHA256 hash |
source | string | No | Origin (e.g., user_upload) |
required | boolean | No | Required for execution (default: true) |
Detection and Prevention
Optional rules or recommendations attached to a procedure:
toml
[[procedures.detection]]
content_type = "sigma"
content = """
title: Scheduled Task Creation
detection:
selection:
EventID: 4698
"""
[[procedures.prevention]]
content = "Block scheduled task creation via AppLocker policy"| Field | Type | Required | Description |
|---|---|---|---|
content_type | string | No | Format type (e.g., sigma, yara) |
content | string | Yes | Rule or recommendation content |
MCZ Archive Format
MCZ files are tar.xz compressed archives containing a procedure TOML and its associated files. The file extension is .mcz.
Structure
procedure_name.mcz (tar.xz)
+-- manifest.toml
+-- procedure.toml
+-- files/
+-- agent.exe
+-- config.jsonmanifest.toml
toml
[package]
format_version = "1.0"
created_at = "2025-01-01T00:00:00Z"
created_by = "MACAT v0.3.0"
encryption = "none"
[contents]
procedure_file = "procedure.toml"
files_dir = "files"
file_count = 2
total_size = 1048576| Field | Type | Description |
|---|---|---|
package.format_version | string | Archive format version (currently "1.0") |
package.created_at | string | RFC 3339 timestamp |
package.created_by | string | Creator identifier |
package.encryption | string | Encryption scheme (currently "none") |
contents.procedure_file | string | Filename of the procedure TOML |
contents.files_dir | string | Directory containing files |
contents.file_count | integer | Number of files |
contents.total_size | integer | Total size of all files in bytes |
Import and Export Behavior
When exporting to MCZ:
- Files with
location = "db"are extracted from the database - File content is stored in the
files/directory - File references are updated to
location = "archive"withpath_in_archiveset - Duplicate filenames are handled automatically
When importing from MCZ:
- Files are extracted from the archive
- Content is compressed and stored in MACAT's database
- File references are updated to
location = "db" - Duplicate files are deduplicated by name and folder
Full Example
toml
id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
name = "Persistence Campaign"
version = 1
description = "Test persistence mechanisms"
tags = ["persistence", "detection-engineering"]
[[procedures]]
id = "11111111-2222-3333-4444-555555555555"
name = "Scheduled Task Creation"
description = "Creates a scheduled task for persistence"
primary_technique = "T1053.005"
primary_tactic = "persistence"
mitre_tactics_ref = ["persistence", "execution"]
supported_platforms = ["windows"]
possible_defenses = ["edr", "siem"]
tags = ["ransomware"]
[[procedures.procedure_steps]]
executor = "powershell"
command = "schtasks /create /tn #{task_name} /tr calc.exe /sc daily"
order = 0
privilege = true
[[procedures.cleanup_steps]]
executor = "powershell"
command = "schtasks /delete /tn #{task_name} /f"
order = 0
[[procedures.dependency_checks]]
dependency_check_executor = "powershell"
dependency_check_command = "Get-Command schtasks"
name = "Check schtasks"
order = 0
[[procedures.variables]]
name = "task_name"
var_type = "string"
default = "MACATTask"
description = "Name of the scheduled task"
[[procedures.detection]]
content_type = "sigma"
content = """
title: Scheduled Task Creation
detection:
selection:
EventID: 4698
"""