Home  /  Blog  /  Wazuh Custom Rule Development Guide

● SOC

Wazuh Custom Rule Development Guide

Out of the box Wazuh ships thousands of rules, but real detection engineering means writing your own. Custom rules are how you catch the threats specific to your applications, suppress your own noise and raise the alerts that matter. Here is a practical guide to writing, levelling and safely testing Wazuh rules.

Published 26 June 2026 11 min read Codesecure SOC Engineering SOC

Key Takeaways

  • Wazuh rules are written in XML and evaluate the fields a decoder has already extracted from a log. Custom rules belong in local_rules.xml so upstream updates never overwrite them.
  • Rule levels run 0 to 16. Level 0 means store but do not alert; higher levels indicate higher severity, and you alert and escalate based on the level.
  • Rules match on fields: the decoded program name, specific extracted fields, regex patterns, and parent rule relationships through if_sid and if_matched_sid.
  • Frequency and composite rules detect patterns across multiple events, such as repeated failed logins within a time window, which single-event rules cannot catch.
  • Always test with wazuh-logtest before deploying. It shows which decoder and rule a sample log triggers, so you validate detection without touching production alerting.

How Wazuh Rules Work

Wazuh rules sit at the second stage of the analysis pipeline. First a decoder parses a raw log and extracts fields (such as the source IP, username or program name). Then the rules engine evaluates those decoded fields against rule definitions and, when a rule matches, generates an alert at the rule's severity level. Rules never parse raw text directly; they work on the structured output the decoder produced, which is why good detection depends on good decoding.

Wazuh ships a large library of built-in rules covering common operating systems, services and attack patterns. These live in the ruleset directory and are updated with the product, so you should never edit them directly. Instead, custom and override rules go in local_rules.xml (and custom decoders in local_decoder.xml), which survive upgrades.

Each rule has a unique rule ID. Built-in rules use reserved ID ranges, so custom rules should use IDs of 100000 and above to avoid collisions. A rule also has a level, optional groups for classification, and matching conditions that decide when it fires.

Rule Structure and Levels

A Wazuh rule is an XML element with an id, a level and a set of matching conditions. A minimal rule looks like this in concept: a rule element with id and level attributes, a match or field condition inside, and a description that becomes the alert text. The description is what an analyst reads in the dashboard, so it should be clear and specific.

The level attribute, from 0 to 16, drives everything downstream. Level 0 is special: the event is processed and stored but generates no alert, which is how you deliberately silence known-benign events. Levels rise with severity: low levels for informational events, mid levels for notable activity such as authentication failures, and high levels (12 and above) for serious events such as successful exploitation or repeated attack patterns. Alerting, escalation and integrations (email, TheHive, n8n) are all triggered by thresholds on the level.

Because the level governs response, levelling is a detection-engineering decision, not an afterthought. Set levels so that the events worth waking someone for are clearly separated from the events worth keeping but not chasing. Consistent levelling across your ruleset is what makes alert triage manageable.

Need Help Designing Your Wazuh Deployment?

Codesecure deploys and tunes Wazuh-based SOC stacks (manager, indexer, dashboard, agents, custom rules and decoders) for businesses across India, Singapore, UAE and Malaysia. ISO/IEC 27001:2022 certified delivery, named OSCP and CISSP consultants, fixed-price proposals.

See SOC and SIEM Services →

Field Matching and Rule Relationships

Rules match in several ways. The simplest condition matches the program name the decoder identified (for example sshd) so the rule only considers logs from that source. Beyond that, rules use field conditions to test specific decoded fields, match for plain substring matching, and regex (and the more efficient pcre2) for pattern matching against the log or extracted fields.

Rules also relate to one another, which is what makes the engine powerful. The if_sid condition makes a rule a child of another rule, so it is only evaluated when the parent has already matched; this lets you write a broad parent rule and then narrower children that refine the alert. if_matched_sid and related conditions express that a rule should fire only when another rule has matched within a time window, which is the basis of correlation.

A practical pattern is layering: a parent rule recognises a class of event at a low level, and a child rule recognises the dangerous variant of it at a high level. For example, a parent might match any authentication event, while a child matches a successful login by a privileged account from an unusual source and raises the level accordingly.

Frequency and Composite Rules

Some attacks are invisible in any single event but obvious across many. A single failed SSH login is routine; thirty failures from one source in a minute is a brute-force attempt. Wazuh detects these with frequency rules, which fire when a matching condition occurs a set number of times within a time window.

A frequency rule specifies a frequency (how many matching events) and a timeframe (the window in seconds), and usually uses if_matched_sid to count occurrences of a child rule. Grouping conditions such as same_source_ip or same_user ensure the count is per attacker or per account rather than across unrelated events, which is what makes the alert meaningful.

Composite and frequency rules are how Wazuh moves from single-event detection to behavioural detection: repeated failures, password spraying across many accounts, a burst of denied firewall connections, or a sequence of suspicious actions on one host. These rules turn raw event streams into the patterns an analyst actually cares about.

Testing Rules with wazuh-logtest

The single most important habit in Wazuh rule development is testing before deploying. The wazuh-logtest tool (run on the manager) takes a sample log line on standard input and shows exactly how Wazuh processes it: which decoder parsed it, which fields were extracted, and which rule matched at what level. This lets you validate a new rule against real log samples without ever touching production alerting.

A safe development loop looks like this: capture a representative raw log line for the activity you want to detect, paste it into wazuh-logtest to see the current decoder and rule behaviour, write or adjust your rule in local_rules.xml, reload the analysis engine, and run wazuh-logtest again to confirm your rule now matches at the intended level. Iterate until the sample, and a few benign variants, behave exactly as intended.

Testing also guards against two classic mistakes: a rule that never fires because it depends on a field the decoder did not extract, and a rule that fires far too often because its match is too broad. wazuh-logtest surfaces both immediately. Pair it with a small library of known-good and known-bad sample logs and you have a repeatable, low-risk way to grow your detection coverage.

Drowning in Alerts or Missing Logs?

Whether you need a log source review, a retention and storage strategy, custom rule development or a full Wazuh tuning engagement, our SOC lead is available for a 30-minute free scoping call.

Talk to a SOC Engineer →

Detection Engineering Best Practices

Good Wazuh rule development follows a few durable principles. Keep all custom logic in local_rules.xml with IDs at 100000 or above. Write clear, specific descriptions, because they are the alert text your analysts triage at 2am. Assign levels deliberately so severity reflects real response priority, and use level 0 to suppress known noise rather than deleting events.

Use groups to classify rules (for example authentication, attack, compliance, or MITRE ATT&CK technique tags) so dashboards and reporting can slice detections meaningfully. Prefer the more efficient pcre2 matching over older regex where you can, and avoid overly broad patterns that match everything and bury real alerts.

Finally, treat rules as living code: version-control local_rules.xml, document why each non-obvious rule exists, and review the ruleset as your environment and threats change. Detection engineering is iterative; the goal is a ruleset that catches the threats that matter to your applications while keeping the alert queue small enough for a human to act on.

SHARE

Frequently Asked Questions

Where should I put custom Wazuh rules?

In local_rules.xml, not in the shipped ruleset files. The built-in rules are updated with the product, so editing them directly means losing your changes on upgrade. Custom rules in local_rules.xml survive updates. Use rule IDs of 100000 and above to avoid colliding with reserved built-in ranges.

What do Wazuh rule levels mean?

Levels run from 0 to 16. Level 0 means the event is processed and stored but produces no alert, used to silence known-benign events. Higher levels indicate higher severity, with 12 and above typically reserved for serious events such as successful exploitation or attack patterns. Alerting and escalation are triggered by thresholds on the level.

How do I detect brute-force attacks in Wazuh?

Use a frequency rule. It fires when a matching condition (such as a failed login child rule) occurs a set number of times within a timeframe, with grouping like same_source_ip so the count is per attacker. This turns many individual failed-login events into a single meaningful brute-force alert.

How do I test a Wazuh rule before deploying it?

Use the wazuh-logtest tool on the manager. Paste a sample raw log line and it shows which decoder parsed it, which fields were extracted and which rule matched at what level. Iterate by adjusting the rule in local_rules.xml, reloading the engine and re-running wazuh-logtest until the sample behaves as intended, all without touching production alerting.

What is the difference between if_sid and if_matched_sid?

if_sid makes a rule a child of another rule, so it is only evaluated after the parent has matched, used to refine a broad parent into specific children. if_matched_sid is used in frequency and correlation rules to fire only when another rule has matched a set number of times within a time window, which is how Wazuh detects patterns across events.

Can Codesecure write custom Wazuh detection rules for us?

Yes. Codesecure builds custom Wazuh rulesets tuned to your applications and threat model, including frequency and correlation rules, MITRE ATT&CK mapping, noise suppression and validation with wazuh-logtest. ISO/IEC 27001:2022 certified delivery with named OSCP, CEH and CISSP consultants across India, Singapore, UAE and Malaysia.

CS

Codesecure SOC Engineering

OSCP / CEH / CISSP Certified SOC Engineers

Codesecure Solutions is ISO/IEC 27001:2022 certified and builds open-source SOC and SIEM platforms on Wazuh, TheHive, Cortex, MISP and n8n for businesses across India, Singapore, UAE and Malaysia. Named OSCP, CEH and CISSP consultants. We design log pipelines, write custom decoders and rules, and run 24x7 detection engineering programmes.

✓ ISO/IEC 27001:2022 Certified

Turn Wazuh Into Detection Tuned For Your Threats

Codesecure writes and tunes custom Wazuh rulesets so your SOC catches the threats specific to your applications while keeping the alert queue small enough to act on. Frequency rules, MITRE ATT&CK mapping and validated testing, delivered by named OSCP and CISSP consultants.