Structure
S4E playbooks are declarative workflows defined in YAML or JSON. Each playbook describes a sequence of steps --- actions, conditions, parallel blocks, and delays --- that execute in response to a trigger event.
Top-Level Fields
id: pb-critical-vuln-response
name: Critical Vulnerability Response
version: "1.0.0"
description: Automated response workflow for critical findings.
trigger:
event: finding.new
conditions:
severity: critical
steps:
- ...
on_failure: abort
max_retries: 0
timeout_minutes: 60
tags:
- security
- automated
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique playbook identifier. |
name |
string | Yes | Human-readable name. |
version |
string | Yes | Semantic version. |
description |
string | No | Purpose and scope of the playbook. |
trigger |
object | Yes | Event that initiates execution. |
steps |
array | Yes | Ordered list of steps to execute. |
on_failure |
string | No | Global failure strategy: abort, continue, retry. |
max_retries |
integer | No | Maximum retry count for the entire playbook. |
timeout_minutes |
integer | No | Maximum execution time before automatic abort. |
tags |
array | No | Labels for filtering and organization. |
Trigger Configuration
The trigger block defines when the playbook starts.
trigger:
event: finding.new
conditions:
severity:
$in: [critical, high]
asset_tags:
$contains: production
Supported trigger events:
| Event | Description |
|---|---|
finding.new |
A new finding is created. |
finding.status_changed |
A finding status is updated. |
scan.completed |
A scan finishes execution. |
scan.failed |
A scan fails. |
action.completed |
An action finishes execution. |
manual |
Triggered manually via API or UI. |
schedule |
Triggered on a cron schedule. |
Step Types
Action Step
Executes a registered action with the given parameters.
steps:
- id: notify-team
name: Notify Security Team
type: action
action_ref: act-slack-notify
parameters:
channel: "#security-alerts"
message: "Critical finding: {{ finding.title }} on {{ finding.asset.name }}"
on_success: next
on_failure: abort
Condition Step
Evaluates an expression and branches execution.
steps:
- id: check-severity
name: Check Severity Level
type: condition
expression: "{{ finding.cvss }} >= 9.0"
on_true: isolate-host
on_false: notify-team
Parallel Step
Runs multiple sub-steps concurrently.
steps:
- id: parallel-response
name: Parallel Initial Response
type: parallel
branches:
- id: notify
action_ref: act-slack-notify
parameters:
channel: "#security-alerts"
message: "Responding to {{ finding.title }}"
- id: create-ticket
action_ref: act-jira-create
parameters:
project: SEC
summary: "{{ finding.title }}"
priority: Critical
join: all
The join field controls when parallel execution completes:
all--- Wait for all branches to finish.any--- Continue when the first branch finishes.
Delay Step
Pauses execution for a specified duration.
Duration supports s (seconds), m (minutes), h (hours).
Approval Step
Pauses execution until a human approves or rejects.
steps:
- id: approve-isolation
name: Approve Host Isolation
type: approval
approvers:
- role: security_lead
timeout: 4h
on_timeout: abort
Step Fields Reference
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique step identifier within the playbook. |
name |
string | Yes | Human-readable step name. |
type |
string | Yes | Step type: action, condition, parallel, delay, approval. |
action_ref |
string | Conditional | Action ID to execute (required for action type). |
parameters |
object | No | Key-value parameters passed to the action. |
on_success |
string | No | Next step ID or next (default) or end. |
on_failure |
string | No | Behavior on failure: abort, continue, retry, or a step ID. |
max_retries |
integer | No | Retry count for this step. |
retry_delay |
string | No | Delay between retries (e.g., 30s, 5m). |
timeout |
string | No | Maximum step execution time. |
Variable Substitution
Use {{ }} syntax to reference data from the trigger event or previous step outputs.
parameters:
message: "Finding {{ finding.id }}: {{ finding.title }}"
asset_name: "{{ finding.asset.name }}"
previous_result: "{{ steps.notify-team.output.message_ts }}"
Available Context Variables
| Variable | Description |
|---|---|
{{ finding.* }} |
Fields from the triggering finding. |
{{ scan.* }} |
Fields from the triggering scan. |
{{ asset.* }} |
Asset associated with the trigger event. |
{{ steps.<step_id>.output }} |
Output from a completed step. |
{{ steps.<step_id>.status }} |
Status of a completed step. |
{{ env.<variable> }} |
Environment variable from configuration. |
{{ now }} |
Current ISO 8601 timestamp. |
Error Handling
Step-Level Error Handling
Each step can define its own failure behavior:
steps:
- id: block-ip
name: Block Malicious IP
type: action
action_ref: act-block-ip
parameters:
ip_address: "{{ finding.source_ip }}"
on_failure: retry
max_retries: 3
retry_delay: 10s
Fallback Steps
Route to a fallback step when the primary step fails:
steps:
- id: auto-remediate
name: Auto Remediate
type: action
action_ref: act-auto-patch
on_failure: manual-escalation
- id: manual-escalation
name: Escalate to Team
type: action
action_ref: act-slack-notify
parameters:
message: "Auto-remediation failed. Manual intervention required."
Warning
Circular step references (e.g., step A fails to step B, step B fails to step A) are detected and rejected at validation time.
Complete Example
id: pb-critical-vuln-response
name: Critical Vulnerability Response
version: "1.2.0"
description: Automated triage and response for critical vulnerabilities.
trigger:
event: finding.new
conditions:
severity: critical
steps:
- id: check-asset-criticality
name: Check Asset Criticality
type: condition
expression: "{{ finding.asset.tags }} contains 'production'"
on_true: parallel-response
on_false: low-priority-notify
- id: parallel-response
name: Immediate Response
type: parallel
branches:
- id: slack-alert
action_ref: act-slack-notify
parameters:
channel: "#incidents"
message: "CRITICAL: {{ finding.title }} on {{ finding.asset.name }}"
- id: jira-ticket
action_ref: act-jira-create
parameters:
project: SEC
summary: "[CRITICAL] {{ finding.title }}"
join: all
on_success: approve-remediation
- id: approve-remediation
name: Approve Remediation
type: approval
approvers:
- role: security_lead
timeout: 2h
on_timeout: low-priority-notify
on_success: remediate
- id: remediate
name: Execute Remediation
type: action
action_ref: act-auto-patch
parameters:
finding_id: "{{ finding.id }}"
on_failure: escalate
- id: escalate
name: Escalate to Engineering
type: action
action_ref: act-pagerduty-alert
parameters:
service: infrastructure
urgency: high
- id: low-priority-notify
name: Low Priority Notification
type: action
action_ref: act-email-notify
parameters:
to: [email protected]
subject: "Finding: {{ finding.title }}"
on_failure: abort
timeout_minutes: 120
Next Steps
- CACAO Mapping to learn how S4E playbooks map to the CACAO standard.
- Writing Playbooks for a step-by-step authoring guide.
- Playbooks API for programmatic playbook management.