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.

steps:
  - id: wait-for-patch
    name: Wait for Patch Window
    type: delay
    duration: 30m

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