Exceptions action steps

Exception action steps let workflows add exception items in Elastic Security, so matching events stop generating alerts. Use these named steps instead of a generic kibana.request call to the exceptions API.

Note

These steps live under the security.* step type namespace. They expose an explicit input schema, so parameters are validated at save time and discoverable in the Workflows editor.

Both steps create the same kind of exception item. They differ in which list the item lands on, and therefore in how many rules it affects.

Step Where the item lands What it affects
security.createRuleException The rule's own default exception list: the list that belongs to one rule and isn't shared with any other. The step creates that list if the rule doesn't have one yet. Only that rule.
security.createExceptionListItem An existing exception list that you identify by list_id, usually a shared exception list. The step fails if the list doesn't exist. Every rule linked to that list.

Use these steps for patterns like:

  • Exclude a known-good host from a noisy rule during a maintenance window.
  • Add a reviewed IP address to a shared allowlist that several rules use.
  • Create a temporary exception from an alert, with an expiration time.
  • Re-run the same suppression workflow without duplicating the exception item.

Both exception steps share the same conventions.

All parameters live under with. There are no top-level fields specific to these steps.

Detection rules have two identifiers. The rule_id parameter on security.createRuleException takes the rule object's id (a UUID, at most 36 characters), not the rule's rule_id field. On an alert, that UUID is kibana.alert.rule.uuid.

Each entry pairs a field with an operator. The operators match the operator labels you select when you build an exception in Elastic Security.

Operator Operand Notes
is, is_not value (string) Exact match.
matches, does_not_match value (string) Supports * and ? wildcards.
is_one_of, is_not_one_of values (string array) Match any listed value.
exists, does_not_exist none Don't set value, values, or list.
is_in_list, is_not_in_list list.id and list.type Match against a value list, a saved set of values such as IP addresses or keywords. list.id is the value list's ID, and list.type is its Elasticsearch data type, such as keyword or ip.

A value-list entry can't mix with other entry types in the same item. If any entry uses is_in_list or is_not_in_list, every entry in that item must.

entries is a logical AND. Every entry of an item must match for the exception to apply. Create a separate item for each alternative (OR) condition.

Nested conditions aren't supported. Fields mapped as nested in the source indices, mostly Endpoint objects, can't be targeted from these steps. Add those exceptions in the Elastic Security UI or through the API. Refer to Exception types and value syntax.

expire_time makes the exception temporary. When set, it's an ISO 8601 datetime after which the exception no longer applies. Omit it for an exception that doesn't expire.

Provide item_id when the workflow might run more than once. If you omit item_id, the API assigns a new random identifier on every run, so a retry, a scheduled trigger, or a loop creates a duplicate exception item. When item_id is set and an item with that identifier already exists on the target list, the step skips creation and returns the existing item, or updates it when overwrite is true. overwrite: true requires item_id. Providing overwrite without item_id fails validation.

Creating, skipping, and overwriting all count as success. The outcome output field reports which one happened, so later steps can branch on it. The step fails only on an error, such as a missing rule or list.

On overwrite, existing comments are preserved. The steps don't send comments when they update an item, because the API appends them as new comments. Other item fields are replaced.

Important

item_id isn't scoped to a particular list. If an item with that item_id already exists on a list other than the one the step targets, the step fails rather than skipping, overwriting, or creating a duplicate. The error names the list that holds the conflicting item. Use a different item_id in that case.

The identity that runs the workflow must be able to manage exceptions. Refer to Exception privileges and Workflow authorization.

The examples on this page use Liquid templating to pull values from the workflow's context. consts.* values are constants declared at the top of the workflow, variables.* values come from an earlier data.set step, and event.* is available only in an alert-triggered or event-driven workflow. Refer to Context variables.

Schema convention. In each schema table on this page, the Location column indicates where each parameter sits in the YAML:

  • top level: Alongside type and name, at the top of the step or trigger definition.
  • `with`: Inside the step's with: block.
  • `on`: Inside the trigger's on: block.

Jump to either step:

security.createRuleException · security.createExceptionListItem


Add an exception item to a detection rule's own default exception list. The exception affects only that rule.

Parameter Location Type Required Description
rule_id with string (rule UUID) Yes The rule object's id (UUID), not rule_id. On an alert, use kibana.alert.rule.uuid. The rule's default exception list is created automatically if it doesn't exist yet.
item_id with string No Stable identifier for idempotency. Omit only when a duplicate item on every run is acceptable.
overwrite with boolean No (default false) When true and item_id already exists on this rule's default list, update that item instead of skipping. Requires item_id.
name with string Yes Exception item name.
description with string Yes Exception item description.
entries with array Yes (at least 1) Match conditions for the item. Refer to Shared conventions.
os_types with string[] No OS types the exception applies to: linux, macos, or windows.
tags with string[] No Tags for the item.
expire_time with string (ISO 8601) No Datetime after which the exception no longer applies.
comments with string[] No Comments attached on create. Not sent on overwrite, so existing comments stay.
# Exclude a host from a rule
- name: add_exception_to_rule
  type: security.createRuleException
  with:
    rule_id: "{{ variables.rule_id }}"
    name: "Exclude maintenance host"
    description: "Host is under maintenance"
    entries:
      - field: host.name
        operator: is
        value: "{{ variables.host_name }}"
		
# Temporary exception created from an alert
- name: add_exception_from_alert
  type: security.createRuleException
  with:
    rule_id: "{{ event.kibana.alert.rule.uuid }}"
    name: "Auto exception for {{ event.host.name }}"
    description: "Created by workflow"
    expire_time: "{{ variables.expiration }}"
    comments:
      - "Excluded during the patching window"
    entries:
      - field: host.name
        operator: is
        value: "{{ event.host.name }}"
      - field: user.name
        operator: is_one_of
        values:
          - svc-patching
          - svc-backup
		
# Idempotent: re-running this workflow updates the same item instead of duplicating it
- name: add_or_update_exception
  type: security.createRuleException
  with:
    rule_id: "{{ variables.rule_id }}"
    item_id: "maintenance-window-{{ variables.host_name }}"
    overwrite: true
    name: "Exclude maintenance host"
    description: "Host is under maintenance"
    entries:
      - field: host.name
        operator: is
        value: "{{ variables.host_name }}"
		

Add an exception item to an existing exception list. Adding to a shared exception list affects every rule linked to that list.

To find a list's list_id, search for it on the Shared exception lists page. Refer to Create and manage shared exception lists.

Parameter Location Type Required Description
list_id with string Yes The target exception list's list_id. The list must already exist. This step doesn't create it.
namespace_type with string No (default single) Whether the target list exists in one Kibana space (single) or in every space (agnostic). This is about spaces, not about how many rules use the list. It must match how the list was created.
item_id with string No Stable identifier for idempotency. Omit only when a duplicate item on every run is acceptable.
overwrite with boolean No (default false) When true and item_id already exists on list_id, update that item instead of skipping. Requires item_id.
name with string Yes Exception item name.
description with string Yes Exception item description.
entries with array Yes (at least 1) Match conditions for the item. Refer to Shared conventions.
os_types with string[] No OS types the exception applies to: linux, macos, or windows.
tags with string[] No Tags for the item.
expire_time with string (ISO 8601) No Datetime after which the exception no longer applies.
comments with string[] No Comments attached on create. Not sent on overwrite, so existing comments stay.
# Add an item to a shared exception list
- name: add_exception_to_shared_list
  type: security.createExceptionListItem
  with:
    list_id: corporate-allowlist
    name: "Allow scanner IP"
    description: "Vulnerability scanner traffic"
    entries:
      - field: source.ip
        operator: is
        value: "{{ event.source.ip }}"
		
# Item referencing a value list, in a list that exists in every space
- name: add_value_list_exception
  type: security.createExceptionListItem
  with:
    list_id: global-scanner-allowlist
    namespace_type: agnostic
    name: "Allow approved scanner IPs"
    description: "Source IPs of the approved scanners"
    entries:
      - field: source.ip
        operator: is_in_list
        list:
          id: approved_scanner_ips
          type: ip
		

The following complete workflow runs daily and keeps one allowlist entry current. Because the item carries a stable item_id, each run updates the same item instead of adding a duplicate.

name: security--refresh-scanner-allowlist
description: Keep the scanner allowlist entry current.
enabled: true

version: "1"

triggers:
  - type: scheduled
    with:
      every: "1d"

consts:
  allowlist_id: corporate-allowlist
  scanner_host: build-agent-01

steps:
  - name: add_allowlist_item
    type: security.createExceptionListItem
    with:
      list_id: "{{ consts.allowlist_id }}"
      item_id: "allowlisted-host-{{ consts.scanner_host }}"
      overwrite: true
      name: "Allow {{ consts.scanner_host }}"
      description: "Reviewed build agent"
      entries:
        - field: host.name
          operator: is
          value: "{{ consts.scanner_host }}"
		

Without item_id, running this workflow again creates a second, separate exception item for the same host rather than updating the first. item_id and overwrite: true together make re-runs safe.

Both steps return the same summary of the created, skipped, or overwritten item.

Field Type Description
id string Internal id of the created or existing item.
item_id string The item's item_id.
list_id string The list the item is on.
namespace_type string single or agnostic. Always single for a rule's own default list.
name string The item's name.
created_at string Creation timestamp.
created_by string Creator.
expire_time string Present only if set on the item.
outcome string created, skipped, or overwritten.