Wazuh fix note · active response

Cannot read 'srcip' from data

This line is written by a Wazuh active response, not by the rule engine: the rule fired, the block did not happen. There are two different cases. 1. The alert had no usable source IP in the places the script reads (this page's original case, from reading the code). 2. On Windows agents, measured on 4.14.7, netsh.exe and route-null.exe wrote this line for every alert we sent, including one with a valid data.srcip: the IP was there and was still rejected. Jump to the Windows case.

Dong Nguyen, ATK New Technology · 28 September 2026 · measured on Wazuh 4.14.7 unless stated otherwise · Windows case added 3 October 2026

Stuck on this right now? Email your custom rules or decoders, one sample log line and your Wazuh version to support@atkvn.com. We run them on that exact version and reply within 24 hours with what we find. Free. Remove hostnames, IPs and usernames first. Rather not send them? Run the free pre-check in your browser; your files never leave your machine.

USD 49 is for one fix, in exchange for an anonymised write-up we can publish. After that: USD 149 per problem, paid only after it works on your system.


Case 1 below is built from reading the Wazuh 4.14.7 source and the public documentation. The Windows case was measured on a Windows 11 agent. The Limits section says exactly what each 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.

Test the response directly, with an address you control (we used the documentation range), through the manager API:

curl -k -X PUT "https://<manager>:55000/active-response?agents_list=<agent id>" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"command":"!netsh.exe","alert":{"data":{"srcip":"203.0.113.78"}}}'

The leading ! runs the executable by name. With "command":"netsh" the 4.14.7 API answered The command used is not defined in the configuration. (error 1652) because no <active-response> block used that command yet. On Windows the log is C:\Program Files (x86)\ossec-agent\active-response\active-responses.log.

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">.

On Windows agents (4.14.7, measured): every IP fails

From a 4.14.7 manager we sent active responses to a Windows 11 agent running 4.14.7, through the API as shown above, and read the agent's active-responses.log:

Alert sentnetsh.exeroute-null.exe
only data.win.eventdata.ipAddress = 203.0.113.77Cannot read 'srcip' from dataCannot read 'srcip' from data
only data.srcip = 203.0.113.78Cannot read 'srcip' from dataCannot read 'srcip' from data

Word for word, from the agent:

2026/10/03 19:51:29 active-response/bin/netsh.exe: Cannot read 'srcip' from data
2026/10/03 19:51:39 active-response/bin/route-null.exe: Cannot read 'srcip' from data

The data.srcip row rules out the field name: a plain, valid address was rejected too. Afterwards there was no Wazuh firewall rule and no route for either address on the machine. Note that the Windows responses print the short form of the message, without or invalid IP format.

Why, from the code. At v4.14.7, netsh.c (line 76) and route-null.c (line 29) both call get_srcip_from_json(), which checks the address with get_ip_version(), which calls getaddrinfo() (active_responses.c, line 576). We found no WSAStartup call in active_responses.c, netsh.c or route-null.c; on Windows, the socket functions need it first. That fits the cause proposed in wazuh/wazuh issue 38739, still open. This is our reading of the code plus the result above, not a debugger run.

Workaround: we found no central workaround you can apply from the manager. The check fails before netsh runs, whatever field carries the IP, and the Fix section below (binding, decoder) does not change that on Windows.

Fix

For case 1 (no usable IP in the alert). For the Windows case, see above.

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. For case 1 we have not triggered the message on a running Linux agent or manager, and have not measured which releases print the shorter text. The Windows case was measured on one Windows 11 Pro agent running 4.14.7 with a 4.14.7 manager, by calling the responses through the API; we did not measure 4.14.8 or earlier releases, and the WSAStartup explanation is from reading the code, not a debugger. 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 -sLO https://github.com/xuxu298/rule-doctor-lite/releases/latest/download/rule-doctor-lite.py
sudo python3 rule-doctor-lite.py
Send it

Free answer within 24 hours.

Paste the rule, config or a few sample lines below, with hostnames and IPs removed. We reply within 24 hours with what is wrong. If you want us to fix it: USD 149 per problem, paid only after it works on your system.

Or email support@atkvn.com.