Infra Notes

Wazuh custom rule does not trigger: start with the real event

Before changing rule logic repeatedly, test custom rules with real log samples and confirm the matched decoder or base rule.

Published · Updated

WazuhRulesDecoderTestingSIEM

Problem

A custom Wazuh rule is deployed, but no alert is generated.

Why it happens

The incoming log may not match the expected decoder, field, base rule ID, or pattern.

Recommended approach

Capture the exact event received by Wazuh, run it through wazuh-logtest, and verify each stage: decoding, extracted fields, base rule, and custom rule conditions. Change one assumption at a time.

Verification order

Useful checks:

  • Confirm the event reaches the manager
  • Test the exact event with /var/ossec/bin/wazuh-logtest
  • Record the matched decoder and extracted field names
  • Confirm the parent or base rule.id
  • Inspect /var/ossec/logs/alerts/alerts.json after deployment

Use this when

  • Suppression rules
  • Custom detections
  • ClamAV or YARA rules
  • Application logs
  • Wazuh tuning

Avoid this when

  • When the log is not collected by the agent at all

Capture the event Wazuh actually receives

Do not rebuild the log from memory. Copy one complete event from the agent or manager logs, preserving its timestamp, program name, JSON structure, and field names. wazuh-logtest processes one-line events, so compact multiline JSON first.

bash

sudo /var/ossec/bin/wazuh-logtest -v

Paste the event and inspect all three phases:

  1. Pre-decoding: program name, timestamp, and hostname
  2. Decoding: decoder name and extracted fields
  3. Rule matching: rule ID, level, groups, and description

If Phase 2 does not expose the field referenced by the rule, changing the rule condition will not help; fix or select the decoder first.

Minimal custom-rule example

Store custom rules under /var/ossec/etc/rules/, not the packaged ruleset directory:

xml

<group name="local,application,">
  <rule id="100100" level="7">
    <decoded_as>json</decoded_as>
    <field name="event.action">login_failed</field>
    <description>Application login failed</description>
  </rule>
</group>

Use an ID in your organization’s custom range and confirm the decoded field is exactly event.action. Field paths and values are case-sensitive where the decoder and rule engine treat them as such.

Parent-rule failures

Rules using <if_sid>, <if_group>, or frequency correlation depend on another match. Confirm the real event fires that parent rule in the same test session.

xml

<rule id="100101" level="10" frequency="5" timeframe="60">
  <if_matched_sid>100100</if_matched_sid>
  <same_srcip />
  <description>Repeated application login failures</description>
</rule>

Feed repeated samples into the same wazuh-logtest session when testing frequency, timeframe, or if_matched_sid behavior.

Apply and verify the deployed rule

Saving a rule is enough for a new wazuh-logtest session to load it, but the Wazuh manager must be restarted before the live analysis engine generates alerts with the change:

bash

sudo systemctl restart wazuh-manager
sudo journalctl -u wazuh-manager -n 100 --no-pager
sudo tail -f /var/ossec/logs/alerts/alerts.json

Validate the XML and watch manager startup logs for duplicate rule IDs, invalid elements, or files that failed to load.

References