Wazuh fix note · active response

Cannot read 'srcip' from data

This line is written by Wazuh's firewall-drop active response, not by the rule engine. The alert that triggered the response had no usable source IP in the places the script reads, so it had nothing to block and stopped. The rule fired; the block did not happen.

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


This page is built from reading the Wazuh 4.14.7 source and the public documentation, not from a run on our side. The Limits section says exactly what that covers.

How to check in one minute

The message goes to the active response log of the host where the response ran, the agent or the manager depending on <location>:

grep "Cannot read 'srcip'" /var/ossec/logs/active-responses.log | tail -n 5

Then look at what triggers the response. On the manager:

grep -A8 '<active-response>' /var/ossec/etc/ossec.conf

If it is bound by <level> or <rules_group>, it runs for every matching rule, including rules whose events carry no IP. This lists, per rule ID, the alerts in today's alerts.json that have neither data.srcip nor a Windows ipAddress / destinationIp:

python3 - <<'EOF'
import json, collections
n = collections.Counter()
for line in open('/var/ossec/logs/alerts/alerts.json'):
    try:
        a = json.loads(line)
    except ValueError:
        continue
    d = a.get('data') if isinstance(a.get('data'), dict) else {}
    w = d.get('win') if isinstance(d.get('win'), dict) else {}
    e = w.get('eventdata') if isinstance(w.get('eventdata'), dict) else {}
    if not ({'srcip'} & d.keys() or {'ipAddress', 'destinationIp'} & e.keys()):
        n[a.get('rule', {}).get('id')] += 1
for rule_id, count in n.most_common(20):
    print(rule_id, count)
EOF

Any rule ID in that list that also matches your active response binding will produce this message.

Why it happens

In 4.14.7 the response reads the source IP with get_srcip_from_json() in src/active-response/active_responses.c. Reading the code, it does this, in order:

  1. It needs parameters.alert.data in its input to be an object. If not, there is no IP.
  2. If data.win.eventdata.ipAddress is a string, that is the candidate. If not, it tries data.win.eventdata.destinationIp.
  3. Only if neither Windows field is a string does it read data.srcip.
  4. The candidate must parse as an IPv4 or IPv6 address. If it does not, there is no IP. There is no fall-back to the next field.

When nothing comes back, firewalls/default-firewall-drop.c writes this line to logs/active-responses.log under the install directory and exits with an error:

Cannot read 'srcip' from data or invalid IP format

In 4.14.7 the text ends with or invalid IP format. Public reports, for example wazuh/wazuh issue 11842, quote the shorter form used in the title of this page.

So there are three practical causes:

What it means for rules that use srcip

The message does not mean your rule failed. The rule matched, the alert was written, and only the response step found nothing to act on. But the same decoded field feeds rules: in the Wazuh decoder documentation srcip is one of the static fields, alongside srcuser, dstip, action, status and others. If a source never decodes srcip, rules that rely on it for that source have nothing to read either.

One measured point about static fields: on 4.14.7 we referenced the static field status as <field name="status"> in a rule. wazuh-analysisd -t failed with Failure to read rule 44732. Field 'status' is static and a CRITICAL (1220), and the manager would not start. The static tag <status> loaded cleanly. srcip is in the same static list; we have not run that exact case for srcip. In rules, use the <srcip> option, not <field name="srcip">.

Fix

1. Bind the response only to rules whose events carry an address. Use <rules_id>, which the documentation describes as limiting the command to when the listed rules fire, instead of a level or group that also catches rules without an IP:

<active-response>
  <command>firewall-drop</command>
  <location>local</location>
  <rules_id>100100</rules_id>  <!-- your rule ID(s) -->
  <timeout>600</timeout>
</active-response>

2. Make the decoder name the field srcip for the sources you want to block on. For a regex decoder, <order> maps each capture group to a field name, and srcip is one of the names it accepts. Test the decoder with wazuh-logtest and confirm srcip appears in the decoding phase before relying on the response.

3. Check the value is an address. If the field holds a host name or a placeholder, the response cannot use it, whatever the binding.

Limits of what we measured

What this page says about the message comes from reading the 4.14.7 source (active_responses.c, active_responses.h, firewalls/default-firewall-drop.c) and the public documentation. We have not triggered the message on a running agent or manager, have not tested Windows events, and have not measured which releases print the shorter text. The Python check above is a plain reader of alerts.json; it does not know your active response binding. The one measured item is the static-field load failure, and we measured it for status, not for srcip.

Free check

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

Rule Doctor Lite checks custom rules; it does not read active response settings or active-responses.log, so it will not show this message. It will show rules that never fire.

curl -sO https://raw.githubusercontent.com/xuxu298/rule-doctor-lite/main/rule-doctor-lite.py
sudo python3 rule-doctor-lite.py

Or have it fixed for you.