Rules
Wazuh rules define the detection logic used to identify relevant security activity in normalized events. They describe what should be detected by specifying conditions on event fields. Rules are written in Sigma format with Wazuh-specific extensions for metadata, MITRE ATT&CK mapping, compliance mapping, and dynamic placeholders.
Top-level fields
A valid rule must define top-level identifiers, a detection block, a logsource, and a metadata section, and can optionally add MITRE ATT&CK and compliance mappings.
The following table lists all supported top-level fields in a Wazuh Sigma rule. Fields marked as required must be present for the rule to pass validation.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
String |
Yes |
Globally unique rule identifier (UUIDv4 recommended) |
|
String |
Yes |
Rule maturity status: |
|
String |
Yes |
Findings severity: |
|
Object |
Yes |
Detection logic: selections, keywords, and conditions |
|
Object |
Yes |
Classifies the type of log data the rule targets |
|
Object |
Yes |
Authorship and lifecycle information |
|
String |
No |
Original Sigma rule identifier (UUID), preserved when importing from upstream |
|
Boolean |
No |
Whether the rule is active (default: |
|
Array |
No |
Categorization tags (e.g., |
|
Array |
No |
Known sources of false positives |
|
Object |
No |
MITRE ATT&CK threat intelligence mapping |
|
Object |
No |
Compliance framework mapping |
Wazuh rule sample
The following example demonstrates a complete Wazuh detection rule using all supported blocks:
metadata:
title: Python SQL Exceptions
author: Thomas Patzke
description: Detects SQL exceptions in Python applications according to PEP 249.
id: 9c1c1e3f-21ad-4db0-9bb4-5cf2e9c1b901
sigma_id: 19aefed0-ffd4-47dc-a7fc-f8b1425e84f9
status: stable
level: medium
enabled: true
tags:
- attack.initial-access
- attack.t1190
logsource:
category: application
product: python
detection:
keywords:
- DataError
- IntegrityError
- ProgrammingError
- OperationalError
condition: keywords
falsepositives:
- Application bugs
mitre:
tactic:
- TA0001
technique:
- T1190
subtechnique: []
compliance:
pci_dss:
- "6.5.1"
gdpr:
- Art. 32
Note
For the full Sigma standard, see the Sigma Rules Specification.
Components of Wazuh rules
A Wazuh Sigma rule is composed of the following blocks:
Required
Optional
Detection
The detection block defines when a rule matches an event. It tells the detection engine what to look for in an event and how to combine those checks into a final match decision. It consists of one or more named selections (or keywords) and a condition that combines them using Boolean logic.
Every detection block has two required parts:
Condition: A condition field wires the selections together using Boolean logic (and, or, not) to produce a true/false result for each incoming event.
Selection: One or more named selections (or a keyword list) that define the conditions to check.
Example:
detection:
condition: selection
selection:
event.action: account-locked
event.category|contains: authentication
Warning
All fields referenced in the detection block are validated against the Wazuh Common Schema (WCS). If a field name does not exist in the schema, the detection engine rejects the rule with a structured error identifying the offending field. This prevents rules that appear active but never match because they query a non-existent field.
Selections
A selection is a named object whose keys correspond to existing WCS fields and whose values define the matching criteria. A selection matches when any or all of its field conditions are satisfied, depending on the chosen syntax.
There are two ways to write a selection, depending on whether you want any condition to match or all of them to match:
Syntax |
How it matches |
Example |
|---|---|---|
Field list (implicit OR) |
When you assign a list of values to a single
field, the selection matches if the field equals
any value in the list. This is the "match one of
these" pattern. This rule matches when
|
detection:
selection:
event.action:
- login_failed # or
- authentication_error
condition: selection
|
Field dictionary (implicit AND) |
When you assign multiple fields within a single
selection, the selection matches only when all
field conditions are satisfied simultaneously.
This is the "match all of these together"
pattern. This rule matches when |
detection:
selection:
log.level: ERROR # and
event.kind: event
condition: selection
|
Keywords (implicit OR)
Keyword detection performs value-only searches across all event fields without specifying a target field name.
Use keywords to search for a value anywhere in an event, without targeting a specific field. The detection engine scans all fields and matches if any of them contain the specified string.
Example:
detection:
keywords:
- DataError # or
- IntegrityError
- OperationalError
condition: keywords
Each item in the above list is effectively separated by a logical "OR" operator, meaning that the rule will match if any of the specified keywords are found in any field of the event.
Use keywords for broad, field-agnostic detection (e.g., scanning log messages for error strings when the field name varies by integration). Use named selections when you know exactly which field to target; selections are more precise and less likely to produce false positives.
Conditions
The condition field is a string expression that combines named selections using boolean logic to define when the rule triggers. Each identifier in the condition must correspond to a named selection defined in the same detection object.
condition: (selection_one or selection_two) and not filter
Operator |
Description |
Example |
|---|---|---|
|
Both operands must match |
detection:
sel_severity:
event.severity|gte: 8
sel_message:
message|contains: fatal
condition: sel_severity and sel_message
|
|
At least one operand must match |
detection:
sel_error:
log.level: ERROR
sel_warn:
log.level: WARN
condition: sel_error or sel_warn
|
|
Fires on matching events, but excludes
any event generated by a thread whose
name starts with |
detection:
selection:
event.kind: event
filter:
process.thread.name|startswith: Test
condition: selection and not filter
|
|
Allows for the grouping of different operations |
detection:
sel_high:
event.severity|gte: 8
sel_critical:
log.level: CRITICAL
filter:
process.name: monitor
condition: (sel_high or sel_critical) and not filter
|
See Sigma Conditions for the full specification of condition syntax.
Modifiers
Modifiers change how a field's value is compared. They are appended to the field name with the pipe character (|) and can be chained; each modifier in the chain further transforms the comparison.
field_name|modifier: value
Multiple modifiers can be chained: field|modifier1|modifier2: value.
Modifier |
What it does |
Example |
|---|---|---|
|
Matches if the field value contains a specified string. Wildcards are inserted around the value. |
|
|
Matches when the field value begins with the specified string. A wildcard is inserted at the end of the value. |
|
|
Matches when the field value ends with the specified string. A wildcard is inserted at the beginning of the value. |
|
|
Encodes the provided value as a Base64 string before comparison. Used to detect commands or parameters that an attacker has Base64-encoded to evade plain-text detection. |
|
|
Generates all three possible Base64 offsets of the value
to account for the byte position where it might appear
inside a larger Base64-encoded blob. Usually preferred
over |
|
|
Transforms the value to a UTF-16 (wide-character) byte
sequence before comparison. Must be chained with an
encoding modifier such as |
|
|
Expands command-line flag prefixes to match all Windows
dash variants: |
|
|
Matches against a PCRE regular expression. Submodifiers
can be chained with
|
|
|
Matches when the field value (an IPv4 or IPv6 address) falls within the specified CIDR subnet. IPv6 addresses are supported in the following formats:
|
|
|
Checks whether the field is present in the event. The
value must be |
|
|
By default, list values are combined with |
event.category|contains|all:
- authentication
- failure
|
|
Matches when the field value is less than the specified number. |
|
|
Matches when the field value is less than or equal to the specified number. |
|
|
Matches when the field value is greater than the specified number. |
|
|
Matches when the field value is greater than or equal to the specified number. |
|
See Sigma Modifiers for additional context on value transformation modifiers.
Log source
The logsource block specifies the type of log data the rule applies to. It tells Wazuh which integration owns the rule and helps organize rules by platform, log type, and service, making it easier to find, filter, and audit your rule library.
The logsource block does not directly affect detection matching. The detection block determines whether an event triggers the rule. logsource is metadata that ties the rule to an integration and organizes it within the Content Manager.
logsource:
product: linux
category: authentication
service: sshd
definition: Ensure sshd authentication logs are collected via the Wazuh Linux integration.
The logsource block has one required field and three optional fields. product is required; every rule must declare the platform or integration it targets. The category, service, and definition fields are optional and can be added to narrow scope, improve grouping, or document prerequisites, but the rule will validate without them.
Field |
Required |
Description |
Example |
|---|---|---|---|
|
yes |
The product or platform generating the
log (for example, |
logsource:
product: linux
|
|
no |
A broad classification of the log type
within the product (for example,
|
logsource:
category: authentication
|
|
no |
The specific service, daemon, or log
channel within the product (e.g.,
|
logsource:
service: sshd
|
|
no |
Free-form notes describing onboarding requirements or prerequisites for the log source. For example, audit policies that must be enabled, agent configuration needed, or specific event IDs to collect. |
logsource:
definition: Script Block Logging must be enabled
|
See Sigma Log Sources for general guidance on log source classification, including the standard combinations of product, category, and service.
Metadata
The metadata block captures authorship, lifecycle, and descriptive information about the rule. It is separate from detection logic; nothing in metadata affects whether a rule fires. Its purpose is to make rules discoverable, attributable, and useful to analysts when a finding appears.
Field |
Required |
Description |
Example |
|---|---|---|---|
|
Yes |
A human-readable rule title is shown in alerts and the rule catalog. Keep titles short and avoid prefixes like "Detects when…" or "This rule will…". |
|
|
No |
The author of the rule. Free-form text; may include contact information such as an email address or handle. |
|
|
No |
Creation date in ISO 8601 format
( |
|
|
No |
Last modification date in ISO
8601 format ( |
|
|
No |
Brief explanation of what the rule detects and the context in which it is useful. |
|
|
No |
URLs or plain-text references (e.g., advisories, CVE IDs, blog posts) that explain the motivation for the rule. |
|
|
No |
Free-form text or a URL providing additional triage context for analysts investigating a finding. |
|
|
No |
List of platforms or products the rule is intended to operate on. |
|
MITRE ATT&CK
The mitre block maps a rule to MITRE ATT&CK tactics, techniques, and subtechniques. Each field is an array of ID strings:
Field |
Description |
Example |
|---|---|---|
|
MITRE ATT&CK tactic IDs. An array of one or more tactic identifiers. |
|
|
MITRE ATT&CK technique IDs. An array of one or more technique identifiers. |
|
|
MITRE ATT&CK subtechnique IDs. An array of one or
more subtechnique identifiers. Use an empty array
|
|
Compliance
The compliance block maps a rule to one or more compliance frameworks. Each key is a normalized framework identifier, and its value is an array of requirement ID strings.
Framework Key |
Full Name |
Example |
|---|---|---|
|
GDPR |
gdpr:
- Art. 32
- Art. 25
|
|
PCI DSS |
pci_dss:
- "2.2.1"
- "6.3.3"
|
|
CMMC |
cmmc:
- AC.1.001
|
|
NIST 800-53 |
nist_800_53:
- AC-3
- AU-2
|
|
NIST 800-171 |
nist_800_171:
- 3.1.1
- 3.3.1
|
|
HIPAA |
hipaa:
- 164.312(a)(1)
|
|
ISO 27001 |
iso_27001:
- A.8.16
- A.9.4.2
|
|
NIS2 |
nis2:
- Art. 21
- Art. 23
|
|
TSC |
tsc:
- CC6.1
- CC7.2
|
|
FedRAMP |
fedramp:
- AC-2
- SI-4
|
Dynamic event field referencing
A Sigma rule's metadata is normally static: the title, tags, mitre, and compliance blocks describe the rule itself and are attached unchanged to every finding it generates. Wazuh extends Sigma with dynamic event field referencing, allowing those metadata fields to embed placeholders that resolve against the triggering event at enrichment time. This process is known as Interpolation. Interpolation means taking static text in your rule YAML and replacing placeholders with values from the current event at detection time, so the final string is dynamically built for each event.
Each finding is written to the wazuh-findings-v5-{logtype}-* index and reflects the specific context of the matched event. For example, the Wazuh agent ID, hostname, or any other field present in the normalized event.
Syntax
You can insert {{ field.path }} placeholders into certain rule metadata fields. When a rule script executes, Wazuh replaces those placeholders with the actual values from the triggering event before writing the finding to the index.
metadata:
title: "Apache segmentation fault in agent {{ wazuh.agent.id }}"
If the event has wazuh.agent.id = "001", the stored finding title becomes: "Apache segmentation fault in agent 001"
Supported fields
Interpolation is applied only to the following fields of the enriched finding's rule object:
titletagsmitre.tactic,mitre.technique,mitre.subtechniquecompliance.*(every framework sub-array)
In the detection block, neither selection nor condition is ever interpolated.
Example
id: ed85157d-711b-4edb-8390-492ec63c92ac
sigma_id: 12345678-90ab-cdef-1234-567890abcdef
logsource:
product: apache-http
tags:
- attack.impact
- attack.t1499.004
- "{{ wazuh.agent.host.name }}"
level: high
status: test
detection:
condition: selection
selection:
message|contains:
- exit signal Segmentation Fault
wazuh.integration.name: apache-http
metadata:
title: "Apache segmentation fault in agent {{ wazuh.agent.id }}"
description: Segmentation faults raised by an Apache worker process.
mitre:
tactic:
- TA0040
technique:
- T1499
subtechnique:
- T1499.004
compliance:
pci_dss:
- "6.2"
- "11.4"
When this rule matches an event where wazuh.agent.id = "001" and wazuh.agent.host.name = "web-prod-01", the resulting enriched finding contains:
{
"title": "Apache segmentation fault in agent 001",
"tags": ["attack.impact", "attack.t1499.004", "web-prod-01"],
"mitre": {
"tactic": ["TA0040"],
"technique": ["T1499"],
"subtechnique": ["T1499.004"]
},
"compliance": {
"pci_dss": ["6.2", "11.4"]
}
}
Placeholder resolution rules
The following table shows conditions and results for dynamic event field referencing:
Situation |
Result |
|---|---|
Field is a string/number/boolean |
Converted to a string and substituted |
Field is an array |
Each element is expanded into the surrounding array |
Field is missing, null, or an object |
Resolves to an empty string, no failure |
The entire value is an empty placeholder |
The field is dropped from the output entirely |
Scope
Interpolation runs after a matching rule is fetched and before the finding is indexed into wazuh-findings-v5-{logtype}-*. The original rule document in the rule index is never modified.