Wazuh fix note · agent events

Wazuh rule with <hostname> matches in wazuh-logtest but never fires for agent events

For an event that comes from an agent, analysisd sets the host name to the agent name before rules run, so <hostname> is compared with that name. The alert still shows the syslog host under predecoder.hostname, which is why the rule looks like it should have matched. wazuh-logtest treats a pasted line as a local event, keeps the syslog host, and matches, so the test passes and production does not.

Dong Nguyen, ATK New Technology · 28 September 2026 · measured on Wazuh 4.14.7 unless stated otherwise


How to check in one minute

Run your line through wazuh-logtest the way analysisd sees an agent event, by passing an agent-style location. Use your agent's ID, name and IP, and the location the event comes from:

/var/ossec/bin/wazuh-logtest -l '[002] (cae) 192.168.8.28->journald'

Paste the log line. If your rule matched with the default location (stdin) but not with this one, the host name condition is the cause.

Why it happens

Every event reaches analysisd with a location. A local event has a location like stdin or a file path; an event from an agent has one that starts with the agent ID, like [002] (cae) 192.168.8.28->journald. In the 4.14.7 source (src/analysisd/cleanevent.c, around lines 543–584), a location that starts with [ makes analysisd take the text between the parentheses, the agent name, as the event's host name. For a local event it keeps the host name read from the syslog header.

<hostname> in a rule is compared with that value (rules.c, around lines 2875–2880), as an OS_Match expression by default. The predecoder.hostname in the alert JSON is parsed again from full_log when the alert is written (json_extended.c), so it shows the syslog host even when the rule compared against the agent name.

We checked it on a 4.14.7 manager with one su line whose syslog host is DN4, a parent rule reached on every run, and two children: one with <hostname>DN4</hostname>, one with <hostname>^cae$</hostname>.

wazuh-logtest -l<hostname>DN4</hostname><hostname>^cae$</hostname>
stdin (default, local event)firesdoes not fire
[002] (cae) 192.168.8.28->journalddoes not firefires
[002] (caesar) 192.168.8.29->journalddoes not firedoes not fire

In all three runs logtest printed hostname: 'DN4' in its decoding phase. The value it prints is not the value the rule compares.

Fix

Limits of what we measured

One release (4.14.7), one single-node throwaway manager, one su line, tested with wazuh-logtest and an agent-style location. We did not send a journald event through a real agent; the live behaviour matches a user report on wazuh/wazuh#39536, where a <hostname> step stopped every event from an agent named cae on two nightly runs. <location> was read from the source, not measured. Events that reach the manager over syslog (<remote>) rather than from an agent are not covered here.

Free check

Check your whole manager for this and other silent rules: Rule Doctor Lite (free, read-only, one Python file).

Lite does not read rule conditions: a rule stopped by <hostname> shows as NO-MATCH, a rule that never matched anything. A Silent Rule Review reads your rules and names this cause when it is the one.

curl -sLO https://github.com/xuxu298/rule-doctor-lite/releases/latest/download/rule-doctor-lite.py
sudo python3 rule-doctor-lite.py

Or have it fixed for you.