Most incident response playbooks are locked inside one SOAR product's proprietary format, so they cannot be reviewed, shared with partners or moved to another platform without being rewritten by hand. OASIS CACAO (Collaborative Automated Course of Action Operations) Security Playbooks Version 2.0 is a JSON specification for describing a course of action as a workflow of steps, commands, agents and targets that both people and orchestrators can read. This guide explains the object model in the specification, how to write and sign a playbook safely, how CACAO fits next to STIX, OpenC2, Sigma and TLP, and how to adopt it without creating a new automation risk. It is written for SOC engineers, incident responders, CTI teams that share response guidance, and architects evaluating playbook portability. It builds on the SOAR and Security Automation Guide and does not repeat its coverage of SOAR platforms in general.
Key takeaways
- CACAO 2.0 is a Committee Specification, not yet an OASIS Standard. Version 2.0 Committee Specification 01 is dated 27 November 2023; the OASIS CACAO TC page (checked 27 October 2026) lists no OASIS Standard approval, so expect tooling support to vary.
- A playbook is a workflow graph in JSON. Nine properties are required, including
workflow_startandworkflow, and steps are typed as start, end, action, playbook-action, parallel, if-condition, while-condition or switch-condition. - Agents, targets and credentials are declared separately from steps. That separation lets a receiving organisation remap who executes a command and against what, without rewriting the logic.
- Signatures and markings are built in. CACAO supports JSON signatures over a JCS (RFC 8785) canonical form plus TLP 2.0, IEP and statement markings, so a shared playbook can carry both integrity and handling rules.
- Treat an imported playbook as executable code. It can carry bash, PowerShell, SSH and HTTP API commands, so validation, review, signature checks and least-privilege execution identities are mandatory before anything runs.
What CACAO is and where it sits
CACAO is produced by the OASIS Collaborative Automated Course of Action Operations Technical Committee, formed in 2019 and co-chaired by Bret Jordan and Allan Thomson, who also edited the 2.0 specification. Version 1.0 reached Committee Specification 01 in January 2021 and Committee Specification 02 in June 2021. Version 2.0 is a substantial revision, not a drop-in update: among other changes, variable syntax moved from the double-dollar form used in 1.x to double underscores (__variable_name__).
CACAO answers one question: "what are the steps to respond to this, in what order, run by whom, against what?" It deliberately sits beside, not over, the other OASIS and FIRST standards that SOC teams already meet.
| Standard | What it describes | How it relates to CACAO |
|---|---|---|
| STIX 2.1 | Threat intelligence objects: indicators, malware, threat actors, relationships | CACAO uses STIX Patterning for while-condition expressions, and playbooks can travel alongside STIX intelligence |
| TAXII 2.1 | Transport for sharing STIX content | A sharing channel; CACAO playbooks can travel alongside intelligence |
| OpenC2 Language Specification 1.0 | A single machine-to-machine command: action, target, optional arguments and actuator | CACAO defines an OpenC2 HTTP command type, so a step can issue an OpenC2 command such as deny or contain |
| Sigma and YARA | Detection logic for logs and files | Both have CACAO command types, so a detection or investigation playbook can carry the rule it runs |
| FIRST TLP 2.0 | Handling rules for shared information | TLP is a built-in CACAO data marking |
| Vendor SOAR formats | Platform-specific workflows and integrations | CACAO is the portable representation; platforms import, export or translate |
OpenC2 is narrower than CACAO: its own specification says sensing, analytics and choosing a course of action are out of scope, and it covers only the acting step. CACAO describes the whole course of action, and an OpenC2 command can be one step inside it. See the STIX and TAXII Guide and the Traffic Light Protocol Guide.
The playbook object model
Section 3.1 of the specification defines the top-level playbook object. Nine properties are required:
| Property | Purpose | Practical note |
|---|---|---|
type | Object type, the value playbook | Validators reject anything else |
spec_version | CACAO version the content conforms to | Pin to the version your tooling validates against |
id | Unique identifier | Keep it stable across versions so references survive updates |
name | Human-readable name | Use the same naming scheme as your runbook library |
created_by | Identifier of the creator | Points to an identity object; matters for trust when shared |
created / modified | Timestamps | Change modified on every content change; signing alone does not change it |
workflow_start | ID of the first step | Must reference a start step in the workflow |
workflow | Dictionary of step objects keyed by step ID | The executable graph |
The optional properties carry most of the operational value. The ones practitioners use most:
- Classification:
playbook_typesfrom an open vocabulary (attack, detection, engagement, investigation, mitigation, notification, prevention, remediation) andplaybook_activities(for example scan-system, match-indicator, restrict-access, disconnect-system, revert-system, restore-data, compose-content, deliver-content). - Lifecycle:
revoked,valid_from,valid_until,derived_fromandrelated_to. Usevalid_untilon any playbook tied to a specific campaign so it expires instead of running for ever. - Risk context:
priority,severity,impactandindustry_sectors, which help a receiving team decide whether a shared playbook is relevant. - Execution summary:
playbook_processing_summary, a summary of the processing features the playbook uses, which helps a receiving platform judge whether it can run the content. - Definitions:
agent_definitions,target_definitions,authentication_info_definitions,extension_definitionsanddata_marking_definitions, referenced from steps by ID. - Integrity and handling:
markingsandsignatures. - Error handling:
workflow_exception, the step to run when the workflow fails.
Workflow steps
| Step type | Behaviour | Design guidance |
|---|---|---|
| start / end | Entry and exit of the graph | Each conditional branch must finish at its own end step |
| action | Runs one or more commands through an agent against targets | Keep one intent per action step so approvals and logs stay readable |
| playbook-action | Calls another playbook | Build small reusable sub-playbooks (enrich IP, isolate host) and compose them |
| parallel | Runs several branches at once | Only for steps with no ordering dependency |
| if-condition | condition expression, required on_true, optional on_false | Use for decision points such as "host is a domain controller" |
| while-condition | Repeats on_true while a STIX Patterning expression holds | Always bound loops with a timeout or counter to avoid runaway execution |
| switch-condition | A switch variable selects a step from cases, with optional default | Good for severity-based routing |
Commands, agents and targets
Every command has a type from the extensible command-type vocabulary plus optional description, version, playbook_activity and external_references. Section 5 of the specification defines manual, bash, CALDERA, Elastic, HTTP API, Jupyter Notebook, Kestrel, OpenC2 HTTP, PowerShell, SSH, Sigma and YARA commands. A manual command is a real first-class option: it lets the same playbook mix human tasks ("call the asset owner") with automated ones, which is how most mature playbooks actually look.
Agents (who or what executes) and targets (what is acted on) come from section 7: group, individual, location, organisation, sector, HTTP API, Linux system, network address, security category and SSH CLI. Because steps refer to them by ID, an organisation that imports a shared playbook remaps the definitions to its own systems and leaves the workflow untouched.
Variables
Variables are wrapped in double underscores, for example __suspect_ip__. They are scoped globally in playbook_variables or locally in step_variables, and the specification reserves constants such as __LOCAL_AGENT__ and __ACTION_TIMEOUT__. Treat any variable that is filled from alert data as untrusted input: an attacker who controls a hostname or URL in a log line should not be able to inject shell syntax into a bash or PowerShell command that interpolates it.
Signing, markings and trust
CACAO is designed for sharing, so it has to answer two questions a receiver will ask: "has this been changed?" and "what am I allowed to do with it?"
- Signatures: the specification uses a JSON signature scheme. The playbook is canonicalised with the JSON Canonicalization Scheme (RFC 8785), hashed (for example with SHA-256) and the result is encoded with base64url. The signature algorithm vocabulary is open. Adding a signature does not change the
modifiedtimestamp, so a signed playbook can be re-signed by a second party without looking like new content. - Markings: statement markings (copyright or terms of use), FIRST TLP 2.0 (TLP:CLEAR, TLP:GREEN, TLP:AMBER, TLP:AMBER+STRICT, TLP:RED) and the FIRST Information Exchange Policy (IEP). A detection playbook containing internal hostnames should never leave the organisation without at least TLP:AMBER.
- Authentication information: HTTP Basic, OAuth2 and user authentication objects can be defined in
authentication_info_definitions. Store references to a secrets manager, never the secret value. A playbook file is copied, diffed, exported and shared, so a password inside it is a leaked credential.
| Risk in a shared playbook | Control | Where it is enforced |
|---|---|---|
| Tampered content in transit or storage | Verify JCS-based signature against a pinned key for that sharing partner | Import pipeline, before validation |
| Hidden destructive command (for example a bash step that deletes data) | Human review of every command step; deny-list of command types allowed for imported content | Review gate in version control |
| Embedded credentials | Reject any authentication object holding a literal secret; resolve from a vault at run time | Linting and secrets scanning |
| Over-privileged execution | One execution identity per agent, scoped to the actions the playbook needs | Orchestrator and IAM |
| Wrong sharing audience | Mandatory TLP marking checked before export | Export pipeline |
| Stale campaign playbook still running | valid_until and periodic review; honour revoked | Playbook library |
Tooling and how to adopt CACAO
Open tooling exists but is young, and support in commercial SOAR products differs by vendor and release: check each platform's own documentation for import, export or translation rather than assuming native support.
- JSON schemas: the
cacao-json-schemasrepository is an OASIS TC Open Repository under the Apache 2.0 licence, and is the natural basis for validation in CI. - CACAO Roaster: an Open Cybersecurity Alliance sub-project, a web application for generating, parsing, validating, editing and visualising CACAO 2.0 playbooks (version 1.3.0 at the time of checking). It can hand playbooks to SOARCA through a configured
SOARCA_URL. - SOARCA: an open-source orchestrator from the COSSAS project that ingests, validates and executes CACAO 2.0 playbooks and supports OpenC2. Its README describes it as built for research and innovation, which is a fair signal about production readiness.
Phased rollout
- Inventory and pick a pilot: list existing runbooks and SOAR workflows, and choose two or three that are stable and well understood, such as phishing triage enrichment and host isolation approval.
- Write them as CACAO with manual steps first: model the workflow, decision points and owners using manual commands only. This gives a reviewable, portable document with no automation risk and exposes gaps in the current process.
- Put playbooks in version control: one JSON file per playbook, schema validation and a linter in CI, mandatory peer review, and a rule that literal secrets fail the build. Treat the repository as production code. See the Detection as Code Guide for the same pattern applied to rules.
- Automate low-risk steps: replace enrichment and notification steps (HTTP API lookups, ticket creation) with automated commands. Keep containment as manual or approval-gated.
- Test in a non-production tenant: run each playbook against test targets with synthetic alerts, record the execution trace and compare it with the expected path for every branch.
- Introduce signing and markings: sign every playbook leaving the repository, pin partner keys, and require a TLP marking on export.
- Share selectively: exchange playbooks with an ISAC, MSSP or parent company only after both sides agree on agent and target remapping and on which command types imported content may use.
- Roll back cleanly: because playbooks are versioned files, rollback means redeploying the previous signed version and setting
revokedon the faulty one. Keep the vendor-native workflow available until the CACAO version has run correctly through several real incidents.
Decision guidance
| Situation | Recommended approach | Trade-off |
|---|---|---|
| Small team, one SOAR or none | Use CACAO as the documentation format for runbooks, mostly manual steps, rendered in a viewer | Little automation gain, but portable and reviewable runbooks |
| Large SOC with one SOAR platform | Keep vendor-native execution, export or author CACAO as the source of truth for review and audit | Translation effort; needs a check that both stay in sync |
| MSSP or group with many tenants | CACAO as the shared library, with per-tenant agent and target definitions | Requires strict signing, review and tenant isolation |
| ISAC or sector sharing community | Share investigation and detection playbooks under TLP; avoid sharing executable containment steps | Receivers must remap and test before running |
| Research or lab | SOARCA plus CACAO Roaster end to end | Not a substitute for a supported platform in production |
Where identity fits
Every automated CACAO step runs as some identity: an orchestrator service account, an API token for an EDR, an SSH key on a jump host or an OAuth client for a firewall manager. These are some of the most powerful non-human identities in the estate, because they exist specifically to isolate hosts, disable accounts and change network policy. Give each agent its own credential, scope it to the actions its playbooks need, keep secrets in a vault referenced from authentication_info_definitions, rotate them, and alert on any use outside an orchestrated run. See the Service Account Security Guide and the Secrets Management Guide.
Detection and measurement
Log every playbook execution with the playbook id, version (modified), signature verification result, triggering alert, each step's start, end and outcome, the agent identity used and any approver. Forward these logs to the SIEM, not just the orchestrator's own store, and protect them from modification by the orchestrator's service accounts.
- Coverage: share of top alert types with a reviewed, version-controlled playbook.
- Validation pass rate: playbooks passing schema validation and linting in CI, target 100 per cent before merge.
- Signed share: share of exported or imported playbooks with a verified signature, target 100 per cent.
- Execution success: runs that reach an end step without hitting
workflow_exception, tracked per playbook. - Time saved: mean time from alert to containment decision before and after automation of enrichment steps.
- Review currency: playbooks reviewed in the last 12 months or after a related incident.
Common failure patterns
- Importing and running shared playbooks unreviewed: a playbook is code. A received file with a PowerShell step is as dangerous as a received script, signature or not.
- Literal credentials in authentication objects: the file ends up in Git, in tickets and in partner exchanges. Reference a vault path and scan for secrets in CI.
- Interpolating alert fields into shell commands: variables filled from attacker-controlled data (hostnames, URLs, email subjects) become command injection into the orchestrator's privileged context. Validate and quote, or pass data through typed API calls.
- Unbounded loops and missing exception handling: a while-condition without a limit or a workflow without
workflow_exceptioncan hammer an API or leave a host half-isolated. - Treating CACAO 1.x content as 2.0: the variable syntax and object model changed. Convert and revalidate rather than editing by hand.
- Automating containment first: teams automate host isolation or account disablement before they trust enrichment, then switch automation off after an outage. Start with enrichment and notification.
Framework mapping
| Framework | Reference | How CACAO supports it |
|---|---|---|
| NIST CSF 2.0 | ID.IM-04 incident response plans established, communicated, maintained and improved | Version-controlled, reviewable playbooks |
| NIST CSF 2.0 | RS.MA-01 response plan executed in coordination with third parties; RS.MI-01 incidents are contained | Executable workflows with defined agents, including partner-run steps |
| NIST CSF 2.0 | RS.CO-03 information shared with designated stakeholders; GV.SC-08 suppliers included in response | Signed, TLP-marked playbook sharing with MSSPs and ISACs |
| NIST SP 800-53 Rev. 5 | IR-4 Incident Handling and IR-4(1) Automated Incident Handling Processes | Automated steps with logged execution |
| NIST SP 800-53 Rev. 5 | IR-8 Incident Response Plan; IR-3 Incident Response Testing | Playbooks as plan components, tested per branch |
| NIST SP 800-53 Rev. 5 | CM-3 Configuration Change Control; SI-7 Software, Firmware, and Information Integrity | Review gates and signature verification for playbook changes |
| ISO/IEC 27001:2022 Annex A | 5.24 incident management planning and preparation; 5.26 response to incidents | Documented, repeatable procedures |
| CIS Controls v8.1 | Control 17 Incident Response Management | Documented process with roles and testing |
See the NIST SP 800-61 Incident Response Guide and the CIS Control 17 Incident Response Management Guide.
Practitioner checklist
- Confirm which CACAO version (2.0 CS01) and which command types your orchestrator actually supports before writing content.
- Store one playbook per JSON file in version control with schema validation, linting and mandatory review.
- Fail the build on literal secrets; reference vault paths from
authentication_info_definitions. - Give every agent its own least-privilege execution identity and alert on its use outside orchestrated runs.
- Start with manual and enrichment steps; gate containment steps behind human approval.
- Bound every while-condition and define a
workflow_exceptionstep. - Sign every exported playbook, verify signatures on import against pinned keys and require a TLP marking.
- Set
valid_untilon campaign-specific playbooks and honourrevokedin your library. - Test every branch in a non-production environment and keep the previous signed version ready for rollback.
Standards and references
- OASIS: CACAO Security Playbooks Version 2.0
- OASIS: Collaborative Automated Course of Action Operations (CACAO) TC
- OASIS: CACAO JSON Schemas TC Open Repository
- OASIS: Open Command and Control (OpenC2) Language Specification Version 1.0
- FIRST: Traffic Light Protocol (TLP) 2.0
- Open Cybersecurity Alliance: CACAO Roaster
- COSSAS: SOARCA open-source CACAO orchestrator
- NIST: SP 800-53 Rev. 5
Related NHI Mgmt Group resources: SOAR and Security Automation Guide · STIX and TAXII Guide · Incident Response Guide · Sigma Rules Guide · MISP Threat Sharing Guide