Rules
Wazuh uses the Sigma rule format as the standard for Ruleset Management detection rules. The Content Manager plugin accepts rules that follow the Sigma specification, extended with Wazuh-specific blocks for metadata, threat intelligence mapping, and compliance coverage.
This page describes the supported rule format, including field requirements, detection logic, supported modifiers, and Wazuh extensions.
For the full Sigma standard, see the Sigma Rules Specification.
Starting example
The following example demonstrates a complete Sigma rule using all supported blocks. Its logsource.product names the integration the rule belongs to, which is a requirement rather than a description of the platform; see Log source.
metadata:
title: Python SQL Exceptions
author: Thomas Patzke
description: Detects SQL exceptions in Python applications according to PEP 249.
sigma_id: 19aefed0-ffd4-47dc-a7fc-f8b1425e84f9
status: stable
level: medium
enabled: true
tags:
- attack.initial-access
- attack.t1190
logsource:
category: application
product: wazuh-generic-1
detection:
keywords:
- DataError
- IntegrityError
- ProgrammingError
- OperationalError
condition: keywords
falsepositives:
- Application bugs
mitre:
tactic:
id:
- TA0001
name:
- Initial Access
technique:
id:
- T1190
name:
- Exploit Public-Facing Application
compliance:
pci_dss:
- "6.5.1"
gdpr:
- Art. 32
Components
A Wazuh Sigma rule is composed of the following blocks:
- Detection
The rule’s matching logic — selections, keywords, and conditions. - Log Source
The type of log data the rule targets. - Metadata
Authorship and lifecycle information (title, author, description, dates, references). - MITRE ATT&CK
Threat intelligence mapping to MITRE tactics, techniques, and subtechniques. - Compliance
Compliance framework mapping (GDPR, PCI DSS, NIST 800-53, etc.).
The sections below describe each component in detail.
Top-level fields
The following fields are the supported top-level fields in a Wazuh Sigma rule. Fields marked Required must be present for the rule to pass validation.
id(String, server-generated) — globally unique rule identifier (UUIDv4). Generated by the Content Manager: leave it out of create and update payloads, where any value supplied is replaced.status(String, required) — rule maturity status:stable,experimental,test,deprecatedorunsupported.level(String, required) — alert severity:informational,low,medium,high, orcritical.sigma_id(String, optional) — original Sigma rule identifier (UUID), preserved when importing from upstream.enabled(Boolean, optional, defaulttrue) — whether the rule is active.tags(Array, optional) — categorization tags (e.g.,attack.initial-access).falsepositives(Array, optional) — known sources of false positives.detection(Object, required) — detection logic: selections, keywords, and conditions.logsource(Object, required) — classifies the type of log data the rule targets. Itsproductfield names the integration the rule belongs to and selects the detector that evaluates it.mitre(Object, optional) — MITRE ATT&CK threat intelligence mapping.compliance(Object, optional) — compliance framework mapping.metadata(Object, required) — other information.
Detection
Required
The detection section defines the rule’s matching logic. It consists of one or more named selections (or keywords) and a condition that combines them using boolean logic.
detection:
condition: selection
selection:
event.action: account-locked
event.category|contains: authentication
The detection section must always contain:
- At least one named selection or a
keywordslist. - A
conditionfield that references those selections.
Important
All fields referenced in the
detectionsection are validated against the Wazuh Common Schema. Rules that reference unknown fields are rejected with a structured error response identifying the offending field names. This prevents silent mismatches where a rule appears active but never triggers because it queries 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:
Field list (implicit OR)
detection:
selection:
event.action:
- login_failed # or
- authentication_error
condition: selection
This rule matches when event.action is either "login_failed" or "authentication_error".
Field dictionary (implicit AND)
detection:
selection:
log.level: ERROR # and
event.kind: event
condition: selection
This rule matches when log.level is "ERROR" and event.kind is "event".
Keywords (implicit OR)
The detection by keywords performs value-only searches across all event fields, without specifying a target field name:
detection:
keywords:
- DataError # or
- IntegrityError
- OperationalError
condition: keywords
Each item in the 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.
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 |
|---|---|---|
and | Both operands must match | selection1 and selection2 |
or | At least one operand must match | sel_error or sel_warn |
not | Negates the following operand | selection and not filter |
( ) | Groups expressions for precedence | (sel_a or sel_b) and not exclusion |
Example: simple condition
detection:
selection:
log.level: ERROR
condition: selection
Example: OR condition
detection:
sel_error:
log.level: ERROR
sel_warn:
log.level: WARN
condition: sel_error or sel_warn
Example: AND with NOT (exclusion pattern)
detection:
selection:
event.kind: event
filter:
process.thread.name|startswith: Test
condition: selection and not filter
Example: multi-selection AND
detection:
sel_severity:
event.severity|gte: 8
sel_message:
message|contains: fatal
condition: sel_severity and sel_message
Reference: See Sigma Conditions for the full specification of condition syntax.
Modifiers
Modifiers transform how a field value is compared during detection. They are appended to the field name using the pipe (|) character:
field_name|modifier: value
Multiple modifiers can be chained: field|modifier1|modifier2: value.
Case sensitivity: string comparison is case-sensitive. This applies to plain equality and to
contains,startswith,endswithand wildcard values alike: a rule matchingUNION SELECTdoes not matchunion selectorUNION sElect. To catch several spellings of a keyword, list them as separate values.Both evaluation paths agree: a deployed detector and logtest compile a rule with the same backend and match it with the same percolator, so a logtest result predicts what the detector will do rather than approximating it.
contains
Matches when the field value contains the specified substring. Wildcards are inserted around the value.
message|contains: timeout
startswith
Matches when the field value begins with the specified string. A wildcard is inserted at the end of the value.
process.thread.name|startswith: Gossip
endswith
Matches when the field value ends with the specified string. A wildcard is inserted at the beginning of the value.
process.thread.name|endswith: "-5"
base64
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.
process.command_line|base64: "/bin/bash"
base64offset
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 base64 when matching a substring inside an encoded stream, and typically chained with contains.
process.command_line|base64offset|contains: "/bin/bash"
wide
Transforms the value to a UTF-16 (wide-character) byte sequence before comparison. Must be chained with an encoding modifier such as base64 or base64offset — it cannot be the final modifier in the chain because the intermediate representation contains null bytes.
process.command_line|wide|base64offset|contains: "ping"
windash
Expands command-line flag prefixes to match all Windows dash variants: -, /, – (en dash), — (em dash), and ― (horizontal bar). Useful for detecting invocations where attackers swap dash characters to evade signatures.
process.command_line|windash|contains: " -enc "
re
Matches the field value against a regular expression.
process.thread.name|re: "^Repair"
Submodifiers can be chained with re|<flag>:
i— case-insensitive matching.m— multi-line mode (^/$match the start/end of each line).s— single-line mode (.also matches newline characters).
cidr
Matches when the field value (an IPv4 or IPv6 address) falls within the specified CIDR subnet.
source.ip|cidr: 10.42.0.0/16
IPv6 addresses are supported in the following formats:
-
Standard: Full 8-group notation with leading zeros.
E.g.,
2001:0db8:85a3:0000:0000:8a2e:0370:7334. -
Compressed: Zero-compression using
::to omit consecutive zero groups.E.g.,
2001:db8:85a3::8a2e:370:7334. -
CIDR: Subnet notation with a prefix length.
E.g.,
2001:db8::/32.
exists
Checks whether the field is present in the event. The value must be true (field must exist) or false (field must be absent).
source.ip|exists: true
all
By default, list values are combined with OR. The all modifier changes the logic to AND, requiring every value in the list to match. Cannot be applied to single-item lists.
event.category|contains|all:
- authentication
- failure
lt
Matches when the field value is less than the specified number.
event.severity|lt: 10
lte
Matches when the field value is less than or equal to the specified number.
event.severity|lte: 3
gt
Matches when the field value is greater than the specified number.
event.severity|gt: 7
gte
Matches when the field value is greater than or equal to the specified number.
event.duration|gte: 5000
Reference: See Sigma Modifiers for additional context on value transformation modifiers.
Log source
Required
The logsource section classifies the type of log data the rule targets. Its category, service and definition fields are descriptive: they help organize rules by their applicable data source, and do not affect detection matching. Its product field is not descriptive — it selects which detector evaluates the rule, as described below.
product
Required
The name of the integration the rule belongs to: it must hold the same value as that integration’s metadata.title.
logsource:
product: wazuh-generic-1
Unlike the rest of the logsource block, product is a routing key rather than a description, because an integration is also a Ruleset Management log type:
- Each integration is registered as a log type.
- A rule’s compiled query is stored in the rule index of the log type its
productnames. - Each integration has a detector, which evaluates the rules stored under its own log type.
So a rule whose product does not name the integration that lists it is stored where that integration’s detector never reads it, and it matches nothing. Rules created through the API are rejected if the two disagree; see Create rule.
Some integrations are named after the platform they collect from, so windows, linux and apache-http are valid product values on a deployment that ships those integrations. That is a consequence of how those integrations are named, not a second, platform-based meaning for the field: wazuh-generic-1, wazuh-fim and wazuh-rootcheck are equally valid, and no platform name is accepted unless an integration carries it. Use category and service to record the telemetry a rule needs.
category
Optional
A broad classification of the telemetry the rule targets (e.g., authentication, process_creation, application, webserver, firewall). Useful for grouping related rules across integrations. Unlike product, this field is descriptive and is not constrained to any list.
logsource:
category: authentication
service
Optional
The specific service, daemon, or log channel the log comes from (e.g., sshd, security, syslog, kerberos). Use this when the log can be attributed to a particular subsystem or event channel.
logsource:
service: sshd
definition
Optional
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
Reference: See Sigma Log Sources for general guidance on log source classification, including the standard combinations of
product,category, andservice. Note thatproductdiverges from that guidance here, as described above: it names an integration rather than a platform. A rule taken from an upstream Sigma ruleset needs itsproductchanged to the integration it is being added to, and a rule exported from Wazuh carries an integration name that other Sigma tooling does not recognize.
Metadata
Required
The metadata block contains authorship and lifecycle fields. Only title is required; the others are optional.
title
Required
Human-readable rule title shown in alerts and the rule catalog.
metadata:
title: Suspicious SSH Login from IPv6
Keep titles short and avoid prefixes like “Detects when …” or “This rule will …”.
author
Optional
The author of the rule. Free-form text; may include contact information such as an email address or handle.
metadata:
author: Security Team
date
Optional
Creation date in ISO 8601 format (YYYY-MM-DD). Auto-managed when the rule is first registered.
metadata:
date: "2026-01-15"
modified
Optional
Last modification date in ISO 8601 format (YYYY-MM-DD). Auto-managed when the rule’s content changes.
metadata:
modified: "2026-03-02"
The modified date changes when the rule is updated.
description
Optional
Brief explanation of what the rule detects and the context in which it is useful. Used by other products and services as a short summary of the rule’s intent — avoid prefixes like “Detects when …” or “This rule will …”.
metadata:
description: SSH login attempts from known malicious IPv6 ranges.
references
Optional
URLs or plain-text references (advisories, CVE IDs, blog posts, documentation) explaining the motivation for the rule or providing background for analysts.
metadata:
references:
- https://example.com/advisory/2025-001
- CVE-2025-22222
documentation
Optional
Free-form documentation text or a documentation URL providing additional context for analysts triaging the alert.
metadata:
documentation: https://docs.example.com/rules/ssh-ipv6
supports
Optional
List of supported platforms, products, or contexts in which the rule is intended to operate.
metadata:
supports:
- linux
- macos
MITRE ATT&CK
Optional
The mitre block maps a rule to MITRE ATT&CK tactics, techniques, and subtechniques. It accepts three category keys, each an object holding an id array and a name array:
tactic
ATT&CK tactics.idholds tactic IDs (e.g.,TA0002,TA0005);nameholds the matching tactic names (e.g.,Execution,Defense Evasion).technique
ATT&CK techniques.idholds technique IDs (e.g.,T1059,T1562);nameholds the matching technique names (e.g.,Command and Scripting Interpreter,Impair Defenses).subtechnique
ATT&CK subtechniques.idholds subtechnique IDs (e.g.,T1059.001);nameholds the matching subtechnique names (e.g.,Command and Scripting Interpreter: PowerShell).
The id and name arrays of a category are parallel: the n-th name describes the n-th ID. Supply name for every entry of a category or for none of them. Categories that do not apply to the rule can be omitted entirely.
The block is stored on the rule as mitre.tactic.id, mitre.tactic.name, mitre.technique.id, mitre.technique.name, mitre.subtechnique.id and mitre.subtechnique.name, and is copied onto every finding the rule produces under wazuh.rule.mitre.*.
Query mitre.subtechnique.id to match rules by subtechnique, or both mitre.technique.id and mitre.subtechnique.id to cover a technique together with its subtechniques.
Example
mitre:
tactic:
id:
- TA0002
- TA0005
name:
- Execution
- Defense Evasion
technique:
id:
- T1059
- T1562
name:
- Command and Scripting Interpreter
- Impair Defenses
subtechnique:
id:
- T1059.001
name:
- "Command and Scripting Interpreter: PowerShell"
Per-entry form
A category may equivalently be written as an array of objects, one per ATT&CK entry, which pairs each ID with its name directly. The two forms are interchangeable and produce identical indexed fields:
mitre:
tactic:
- id: TA0002
name: Execution
- id: TA0005
name: Defense Evasion
technique:
- id: T1059
name: Command and Scripting Interpreter
Deprecated shorthand
A category written as a plain array of ID strings is still accepted, for rules authored against the older documentation:
mitre:
tactic:
- TA0002
technique:
- T1059
This form carries no ATT&CK names, so mitre.tactic.name, mitre.technique.name and mitre.subtechnique.name are left empty. Use one of the two named forms above for new rules.
Compliance
Optional
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.
Supported frameworks
gdpr
GDPRpci_dss
PCI DSScmmc
CMMCnist_800_53
NIST 800-53nist_800_171
NIST 800-171hipaa
HIPAAiso_27001
ISO 27001nis2
NIS2tsc
TSCfedramp
FedRAMP
Example
compliance:
gdpr:
- Art. 32
- Art. 25
pci_dss:
- "2.2.1"
- "6.3.3"
cmmc:
- AC.1.001
nist_800_53:
- AC-3
- AU-2
hipaa:
- 164.312(a)(1)
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. Each finding written to wazuh-findings-v5-{category}* then reflects the specific context of the event that matched — for example, the agent ID, hostname, or any other field present in the normalized event.
Syntax
A placeholder takes the form {{ field.path }}, where field.path is a dot-separated path into the triggering event’s _source document. Whitespace inside the delimiters is trimmed, so {{ wazuh.agent.id }} and {{wazuh.agent.id}} are equivalent. Placeholders may appear anywhere inside a supported field’s value and may be mixed with literal text.
Supported fields
Interpolation is applied only to the following fields of the enriched finding’s wazuh.rule object:
titletagsmitre.tactic.id,mitre.tactic.name,mitre.technique.id,mitre.technique.name,mitre.subtechnique.id,mitre.subtechnique.namecompliance.*(every framework sub-array)
The detection block — both selection and condition — is never 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:
id:
- TA0040
name:
- Impact
technique:
id:
- T1499
name:
- Endpoint Denial of Service
subtechnique:
id:
- T1499.004
name:
- "Endpoint Denial of Service: Application or System Exploitation"
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 wazuh.rule object of the resulting enriched finding contains the following fields, alongside id, sigma_id, level and status, which are copied unchanged:
{
"title": "Apache segmentation fault in agent 001",
"tags": ["high", "apache-http", "attack.impact", "attack.t1499.004", "web-prod-01"],
"mitre": {
"tactic": {
"id": ["TA0040"],
"name": ["Impact"]
},
"technique": {
"id": ["T1499"],
"name": ["Endpoint Denial of Service"]
},
"subtechnique": {
"id": ["T1499.004"],
"name": ["Endpoint Denial of Service: Application or System Exploitation"]
}
},
"compliance": {
"pci_dss": ["6.2", "11.4"]
}
}
wazuh.rule.tags starts with the rule’s level and the integration it belongs to (its logsource.product), followed by the rule’s own tags. Each mitre category keeps its own id and name arrays: a subtechnique appears under subtechnique only, never under technique.
Resolution rules
- Scalars (string, number, boolean) are coerced to their string representation and substituted in place of the placeholder.
- Scalar arrays are expanded — each array element is coerced to a string and contributed as an additional element of the surrounding array. Supported for
tags, theidandnamearrays of everymitrecategory, andcompliance.*. Duplicate values are removed from each of these arrays after interpolation. - Missing, null, or non-scalar (object) values resolve to the empty string. Finding generation never fails because of an unresolved placeholder.
- A field whose value consists solely of a placeholder that resolves to the empty string is dropped from the surrounding array or map. For instance, a tag of
"{{ missing.field }}"will not appear inwazuh.rule.tags. - A
mitrecategory whoseidandnamearrays both end up empty after interpolation is removed fromwazuh.rule.mitreentirely.
Scope
Interpolation runs after the matching rule is fetched and before the enriched finding is indexed. It affects only the document written to wazuh-findings-v5-{category}*. The raw rule document stored in the rule index is unchanged.